hybridgroup / node-bebop

A Node.js client for controlling Parrot Bebop & Bebop2 quadcopters.
http://nodebebop.com
MIT License
146 stars 61 forks source link

mavlink.start not working? #25

Closed Mezcall closed 8 years ago

Mezcall commented 8 years ago

Hello,

I'm trying to run a flightPlan in mavlink format, but i get an error: It seems that this lib cannot parse the string? there is no write method in string type.

Code and error description bellow.

code: var obj = { filepath: "flightPlan.mavlink", type:"flightPlan" }; drone.Mavlink.start(obj);

error: \node_modules\node-bebop\lib\commandToBuffer.js:64 types[part.type].write(buffer, parseInt(part.value, 10), offset); ^

TypeError: types[part.type].write is not a function at path..\node_modules\node-bebop\lib\commandToBuffer.js:64:22 at Array.forEach (native) at writeBuffer (path..\node_modules\node-bebop\lib\commandToBuffer.js:61:11) at module.exports (path..\node_modules\node-bebop\lib\commandToBuffer.js:73:10) at Mavlink.start (path..\node_modules\node-bebop\lib\Mavlink.js:13:16) at path..\node_modules\node-bebop\examples\mavlink.js:11:19 at null. (path..\node_modules\node-bebop\lib\bebop.js:255:7) at null. (path..\node_modules\node-bebop\lib\bebop.js:273:5) at emitOne (events.js:77:13) at Socket.emit (events.js:169:7)

Thank you

deadprogram commented 8 years ago

Hi, @Mezcall according to the docs you need to load the mavlink file onto the drone (for example using FTP), before trying to load it using the Bebop API.

brunoua commented 8 years ago

@deadprogram i load my mavlink file onto the drone using ftp and try "var mav = {filepath:"./internal_000/flightplans", type:"text/plain"}; drone.Mavlink.start(mav);"

but i have this error:

/home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:59 types[part.type].write(buffer, parseInt(part.value, 10), offset); ^ TypeError: Object # has no method 'write' at /home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:59:22 at Array.forEach (native) at writeBuffer (/home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:57:11) at module.exports (/home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:68:10) at Mavlink.start (/home/bruno/app/node_modules/node-bebop/lib/Mavlink.js:13:16) at /home/bruno/app/testes/video.js:16:16 at null. (/home/bruno/app/node_modules/node-bebop/lib/bebop.js:255:7) at null. (/home/bruno/app/node_modules/node-bebop/lib/bebop.js:273:5) at Socket.EventEmitter.emit (events.js:95:17) at Socket. (_stream_readable.js:746:14)

thanks

deadprogram commented 8 years ago

Hi, @brunoua I've not tried that capability yet.

However, I would think that filepath:"./internal_000/flightplans"should be the full path name to the actual MAV file, i.e. filepath:"/home/root//internal_000/flightplans/myplan.mav" or whatever the FTP root is.

Also type should be an enum either "flightPlan" or "mapMyHouse" (not used) according to the Parrot docs:

Start an autonomous flight

    filepath (string): autonomous flight file path from the mavlink ftp root
    type (enum): type of the played mavlink file
        flightPlan: Mavlink file for FlightPlan
        mapMyHouse: Mavlink file for MapMyHouse (not used)

Result:
The autonomous flight will be started if all requirements are met. Requirements are :

    Product is calibrated
    Product should be in outdoor mode
    Product has fixed its GP

That said, from your error, I do not think your code even got that far. Looks like some mismatch in the signature of the API in the JSON file.

brunoua commented 8 years ago

I try this:

"use strict";

var bebop = require("node-bebop"), fs = require("fs");

var drone = bebop.createClient();

var mav = {filepath:"/home/root//internal_000/flightplans/flightPlan.mavlink", type:"flightPlan"}; //var obj = {latitude:"40.6338034", longitude:"-8.6606003", altitude:"2", horizontalAccuracy:"-1", verticalAccuracy:"-1"};

drone.connect(function() { drone.Mavlink.start(mav); //drone.GPSSettings.sendControllerGPS(obj) console.log("test"); });

but have the same error... I'm using node 5.10.1v and Bebop2 with 3.1.0 version.

Have any idea?

deadprogram commented 8 years ago

I would try changing this line https://github.com/hybridgroup/node-bebop/blob/master/lib/Mavlink.js#L13 to:

 var buffer = commandToBuffer(3, "Mavlink", "Start", obj);

Also, I made up that filepath, you need to telnet onto the drone to determine the "real" path.

brunoua commented 8 years ago

@deadprogram I changed the file, however I have another error:

buffer.js:969 throw new TypeError('value is out of bounds'); ^

TypeError: value is out of bounds at checkInt (buffer.js:969:11) at Buffer.writeUInt16LE (buffer.js:1027:5) at Object.module.exports.u16.write (/home/bruno/app/node_modules/node-bebop/lib/types.js:29:14) at /home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:59:22 at Array.forEach (native) at writeBuffer (/home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:57:11) at module.exports (/home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:68:10) at Mavlink.start (/home/bruno/app/node_modules/node-bebop/lib/Mavlink.js:13:16) at /home/bruno/app/testes/video.js:15:16 at null. (/home/bruno/app/node_modules/node-bebop/lib/bebop.js:255:7)

I went into the drone and pwd used in mavlink folder, which gave me "internal_000/flightPlan/".

Any suggestion?

brunoua commented 8 years ago

@deadprogram can you help me? I think that the library doesn't accept the argument "3".

Regards

deadprogram commented 8 years ago

@brunoua you are correct. The current implementation seems to be limited to only supporting numeric params. Perhaps @johan-olsson might be willing to jump in to this conversation with some implementation details for adding string params?

aCard0s0 commented 8 years ago

I have trying the same solution then @brunoua. I getting the same error. I trying debug your lib but javascript isn't my strong. @deadprogram and @johan-olsson any suggestion will be welcome. Thank you so much!

brunoua commented 8 years ago

@deadprogram Thank you for your concern. I await that @johan-olsson will help us with this issue.

Regards

brunoua commented 8 years ago

@deadprogram there is no progress on this issue?

Regards Bruno Barbosa

deadprogram commented 8 years ago

From what I can tell, we're going to need to add code to handle commands.json when "type":"string" and "type":"enum"in this function https://github.com/hybridgroup/node-bebop/blob/master/lib/commandToBuffer.js#L46

deadprogram commented 8 years ago

OK it looks to me that that this might actually be the same core problem as https://github.com/hybridgroup/node-bebop/issues/17 specifically https://github.com/hybridgroup/node-bebop/issues/17#issuecomment-205327905

brunoua commented 8 years ago

@deadprogram I agree with the observation ... Is there any way to make this change quickly? There is another way to pass arguments to the function?

Thanks again for the available time. It is very important to me that this feature is working

deadprogram commented 8 years ago

Understood, I am looking into it a bit.

Question: how did you create your MavLink file? I will need something for testing...

brunoua commented 8 years ago

@deadprogram I created with the application freeflight 3. I will send you by email

brunoua commented 8 years ago

@deadprogram I sent for you right now by email

brunoua commented 8 years ago

@deadprogram if you have news please tell me

Regards

odasneves commented 8 years ago

@deadprogram im having the same problem. Is there any solution yet ? It's really important for my application to have this feature. thanks =)

brunoua commented 8 years ago

@deadprogram I've been debugging the library and noticed that in the function

"u16": { read: function(buffer, index) { return buffer.readUInt16LE(index); }, write: function(buffer, data, index) { console.log(data + " " + index); buffer.writeUInt16LE(data, index); return buffer; }, length: 2 }

the value of the "data" when i run the start command is -1. Thus, changing this function for

"u16": { read: function(buffer, index) { return buffer.readUInt16LE(index); }, write: function(buffer, data, index) { console.log(data + " " + index); if(data!=-1){ buffer.writeUInt16LE(data, index); } else{buffer.writeUInt16LE(0, index);}
return buffer; }, length: 2 }

,the error doesn't pop , however, nothing happens, the mavlink doesn't start.

Regards

deadprogram commented 8 years ago

Hi, @brunoua & @gustavonev3s

I'm experimenting with a new branch here https://github.com/hybridgroup/node-bebop/tree/bugfix/mavlink-commands

It is a pretty big refactoring of the code that parses the commands stored in the JSON dictionary.

One change is to the signature of the commands that take multiple params. In the case of Mavlink.start() it should now be:

drone.Mavlink.start("flightPlan.mavlink", 0);

I'm still unsure about the pathname param, seems like it might be limited to 24 characters in length?

I cannot do any outdoor testing right this moment, but perhaps someone else can help out on that regard. I did test the case when a single param is passed e.g. drone.MediaStreaming.videoEnable(1); it seems to work correctly.

Anyhow, please let me know if anyone can try this out and report back. Thanks!

brunoua commented 8 years ago

@deadprogram I created the following script now:

"use strict";

var bebop = require("node-bebop"), fs = require("fs");

var drone = bebop.createClient();

drone.connect(function() {

drone.Mavlink.start("flightplan.mavlink", 0);

drone.on("MavlinkPlayErrorStateChanged", function(data){ console.log(data); });

drone.on("MavlinkFilePlayingStateChanged",function(data){ console.log(data); });

});

tomorrow I will try and put here feedback.

Thank you for your attention, Bruno Barbosa

deadprogram commented 8 years ago

Sounds good. Just make sure you put your "flightplan.mavlink" file at the root of the FTP directory (at least according to the Parrot docs)

brunoua commented 8 years ago

@deadprogram I tested this script:

"use strict";

var bebop = require("node-bebop"), fs = require("fs");

var drone = bebop.createClient();

drone.connect(function() {

drone.Mavlink.start("/internal_000/flightplans/flightplan.mavlink", 0);

drone.on("MavlinkPlayErrorStateChanged", function(data){ console.log(data); });

drone.on("MavlinkFilePlayingStateChanged",function(data){ console.log(data); });

});

however I get the following error:

buffer.js:700 if (string.length > 0 && (length < 0 || offset < 0)) ^

TypeError: Cannot read property 'length' of undefined at Buffer.write (buffer.js:700:13) at Object.module.exports.string.write (/home/bruno/app/node_modules/node-bebop/lib/types.js:86:14) at /home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:155:22 at Array.forEach (native) at writeBuffer (/home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:154:11) at module.exports (/home/bruno/app/node_modules/node-bebop/lib/commandToBuffer.js:170:10) at Mavlink.start (/home/bruno/app/node_modules/node-bebop/lib/Mavlink.js:13:16) at /home/bruno/app/testes/mavlink.js:11:16 at null. (/home/bruno/app/node_modules/node-bebop/lib/bebop.js:255:7) at null. (/home/bruno/app/node_modules/node-bebop/lib/bebop.js:273:5)

I tested several paths, such as "/data/ftp/internal_000/flightplans/flightplan.mavlink" and just "flightplan.mavlink" but have the same error....

Regards, Bruno Barbosa

brunoua commented 8 years ago

@deadprogram I also tested this script whit the branch ( https://github.com/hybridgroup/node-bebop/tree/bugfix/mavlink-commands):

var bebop = require("node-bebop"), fs = require("fs");

var output = fs.createWriteStream("./video.h264"), drone = bebop.createClient(), video = drone.getVideoStream();

video.pipe(output);

drone.connect(); drone.MediaStreaming.videoEnable(1); // this line should start video

And had this error:

/home/bruno/app/node_modules/node-bebop/lib/types.js:96 return arg.enum[buffer.readInt32LE(index)].name; ^

TypeError: Cannot read property 'name' of undefined at Object.module.exports.enum.read (/home/bruno/app/node_modules/node-bebop/lib/types.js:96:49) at /home/bruno/app/node_modules/node-bebop/lib/bebop.js:330:18 at Array.forEach (native) at Bebop._packetReceiver (/home/bruno/app/node_modules/node-bebop/lib/bebop.js:327:21) at emitTwo (events.js: 100:13) at Socket.emit (events.js:185:7) at UDP.onMessage (dgram.js:529:8)

Regards

deadprogram commented 8 years ago

Hi, @brunoua thanks for all the debug info.

My latest commits allow me to run the following examples without error:

  • examples/piloting.js It flew...
  • examples/takeoff-events.js It flew plus dumped a bunch of events to console
  • examples/gps.js It repeatedly dumped 500 values to the console as expected, since I was indoors and did not have a GPS lock
  • examples/video.js It dumped the video to the file, which I was able to view using my VLC player
  • examples/flightplan.js This is a new example I just created. I used FTP to copy the file you sent me to the drone in the directory under FTP internal_000/flightplans/flightplan.mavlink

I then ran the "flightplan.js" which did not error. I did not expect it to actually do anything, since the drone was not yet in flight, nor had a GPS lock.

You should be able to test all of these. I ran them in Node 4.2 and in Node 5.8

Please let me know how it goes for you.

brunoua commented 8 years ago

@deadprogram I tested your video.js example with node 5.8 and 4.2 and have the same error:

  return arg.enum[buffer.readInt32LE(index)].name;
                                            ^

TypeError: Cannot read property 'name' of undefined at Object.module.exports.enum.read (/home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/types.js:96:49) at /home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/bebop.js:330:18 at Array.forEach (native) at Bebop._packetReceiver (/home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/bebop.js:327:21) at emitTwo (events.js:87:13) at Socket.emit (events.js:172:7) at UDP.onMessage (dgram.js:480:8)

I'm using a bebop 2 with 3.1 version. What about you?

Regards

deadprogram commented 8 years ago

Bebop 1 with 2.0.57

brunoua commented 8 years ago

@deadprogram

I tried to update my version to 3.2.0 and now I get the following error:

/home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/bebop.js:325 if (typeof event.arg !== "undefined") { ^

TypeError: Cannot read property 'arg' of undefined at Bebop._packetReceiver (/home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/bebop.js:325:23) at emitTwo (events.js:100:13) at Socket.emit (events.js:185:7) at UDP.onMessage (dgram.js:530:8)

Any suggestion?

Regards

deadprogram commented 8 years ago

Not really. You can look thru the call stack to try to figure out which new event is breaking the code?

I do not have that version of the HW, and Parrot is notorious for both breaking changes and a lack of developer support. My Bebop1 works with the current code, and unless I could repro your problem, cannot do much about it.

brunoua commented 8 years ago

@deadprogram Is it possible to put my bebop 2 with version 2.0.57?

How can I do that "You can look thru the call stack to try to figure out which new event is breaking the code?"?

deadprogram commented 8 years ago

According to the Parrot docs, the 3.x firmware applies to the Bebop2, and the 2.x to the Bebop1. So, appears not to be possible to change that firmware.

https://github.com/hybridgroup/node-bebop/blob/bugfix/mavlink-commands/lib/bebop.js#L325 is the line of code that fails. I would guess that https://github.com/hybridgroup/node-bebop/blob/bugfix/mavlink-commands/lib/bebop.js#L322 is assigning undefined due to an unknown commandId.

You could try replacing https://github.com/hybridgroup/node-bebop/blob/bugfix/mavlink-commands/lib/bebop.js#L321-L323

with

if (event instanceof Array) {
  event = event[commandId];
  if (!event) {
    console.log("Unknown command id:", commandId);
    return;
  }
}
brunoua commented 8 years ago

@deadprogram I tried this change and got this error:

Unknown command id: 2 /home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/types.js:96 return arg.enum[buffer.readInt32LE(index)].name; ^

TypeError: Cannot read property 'name' of undefined at Object.module.exports.enum.read (/home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/types.js:96:49) at /home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/bebop.js:335:18 at Array.forEach (native) at Bebop._packetReceiver (/home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/bebop.js:332:21) at emitTwo (events.js:100:13) at Socket.emit (events.js:185:7) at UDP.onMessage (dgram.js:530:8)

thank you for your patience

brunoua commented 8 years ago

if I remove the ".name" of /home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/types.js:96, the error disappears, but nothing happens

brunoua commented 8 years ago

@deadprogram Version 3.2.0 is also available for bebop 1 (https://community.parrot.com/t5/Bebop-Drone/bd-p/Bebop_EN) if you want to update makes it easier to support the node-bebop

brunoua commented 8 years ago

@deadprogram Ron i think that it's important: I'm trying to change this lines https://github.com/hybridgroup/node-bebop/blob/bugfix/mavlink-commands/lib/types.js#L91-L104 to:

"enum": { read: function(buffer, index, arg) { if (buffer.length - index < 4) { return arg.enum[buffer.readInt16LE(index)].name; } console.log("Enum: " + arg.enum[0].name); console.log("test "+buffer.readInt32LE(index)); return arg.enum[buffer.readInt32LE(index)].name;

},
write: function(buffer, value, index) {
  var data = parseInt(value, 10);
  buffer.writeInt32LE(data, index);
  return buffer;
},
length: 4

}

and when i execute "node video.js" have this:

Enum: landed test 0 Enum: IMU test 0 Enum: IMU test 1 Enum: IMU test 2 Enum: IMU test 3 Enum: IMU test 4 Enum: IMU test 5 Unknown command id: 2 Enum: open test 0 Enum: GPS test 1 Enum: GPS test 0 Enum: GPS test 2 Enum: GPS test 3 Enum: playing test 1 Enum: flightPlan test 1751607660 /home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/types.js:98 return arg.enum[buffer.readInt32LE(index)].name; ^

TypeError: Cannot read property 'name' of undefined at Object.module.exports.enum.read (/home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/types.js:98:49) at /home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/bebop.js:334:18 at Array.forEach (native) at Bebop._packetReceiver (/home/bruno/Projeto/node-bebop-bugfix-mavlink-commands/lib/bebop.js:331:21) at emitTwo (events.js:100:13) at Socket.emit (events.js:185:7) at UDP.onMessage (dgram.js:530:8)

do you get any conclusion?

deadprogram commented 8 years ago

Updated my BB1 to 3.2.0 firmware. Made several changes to handle unknown commands and enums. Give that a try, the examples are currently running for me without error.

brunoua commented 8 years ago

@deadprogram I could now see streaming video ... I am very grateful! Once I get I'll test the mavlink and put here the feedback. Thank you very much!

brunoua commented 8 years ago

@deadprogram I tested now the flightplan.js, nothing happens, however it prints the following:

ready BatteryStateChanged 92 FlyingStateChanged landed unknown < Buffer 01 0a 02 00 00 00 00 00 00 00 00 00 00 > { state: 'stopped', filepath: '/data/ftp/internal_000/flightplans/flightPlan.mavlink\u0000\u0000\u0000\u0000\u0000', type: 'unknown enum' }

before that I ran the gps.js to make sure it got GPS.

I think it is very close to work

Any suggest?

Regards

brunoua commented 8 years ago

@deadprogram Can you try the flightplan.js outdoor with your drone?

Regards

deadprogram commented 8 years ago

According to the Parrot docs, I think the requirements to be met before calling drone.Mavlink.start() must be based on this:

component (enum): Drone FlightPlan component id (unique)
    GPS: GPS for Drone FlightPlan
    Calibration: Calibration for Drone FlightPlan
    Mavlink_File: Mavlink file for Drone FlightPlan
    TakeOff: Take off

So, make sure you have done a calibration (you can do using FF3 for now), that you have GPS lock, that you have a valid mavlink file, and that you call drone.Piloting.takeOff() before you call drone.Mavlink.start().

brunoua commented 8 years ago

I think that the flightplan have the takeoff function. So this is not needed to start him.

Can i do a calibration with a FF3 app?

Regards.

deadprogram commented 8 years ago

I think, yes. You should be able to do a calibration with ff3, just don't reboot the drone.

brunoua commented 8 years ago

soon as I got it, I will try. if you can test with your drone also please give feedback.

Thanks

deadprogram commented 8 years ago

How do I get the file created by the flight plan off of my phone?

brunoua commented 8 years ago

run once from your mobile phone, then connect to drone via ftp, go to " / internal_000 / flightplans / " and then just transfer the flightplan.mavlink file to your PC.

Got it?

deadprogram commented 8 years ago

Created a flight plan, then nearly lost my drone. It was about 20 meters up, non-responsive... lucky but it crashed into a tree which softened the landing. Seems scratched but undamaged. I think I better find a better location for these tests.

brunoua commented 8 years ago

bad luck, however managed to make the start to mavlink? what may have gone wrong? What is the script that you used?

deadprogram commented 8 years ago

No, that was just using the flight plan software to see what would happen if my script actually worked.

brunoua commented 8 years ago

So if you can test it with your flightplan script please give me a feedback.

I will try to do the same tomorrow morning.