ev3dev / ev3dev-lang

(deprecated) language bindings for ev3dev sensors, motors, LEDs, etc.
GNU General Public License v2.0
56 stars 39 forks source link

Expanding featureset to make API more user-friendly #89

Open WasabiFan opened 9 years ago

WasabiFan commented 9 years ago

I know that @ddemidov has been adding some great features like motor helper functions to the Python lib, and would like to get those implemented in all of our libraries in the repo. @ddemidov can you provide a list of the features that you think should be added to our specification? You have already blazed the trail and figured out how various methods of exposing these APIs can work, so I'd love some of that insight when we are implementing them cross-language.

ddemidov commented 9 years ago

Here is a list of features in python/C++ bindings, that are implemented on top of specification.

1. The motor helper functions were actually a @dlech's idea. In python, a motor provides methods corresponding to each of possible commands. The methods use a great feature of python -- keyword arguments. So user may set some motor parameters and issue a command at the same time. Example:

m = large_motor()
m.run_forever(speed_regulation_enabled='on', speed_sp=750)

Keyword arguments are not available in C++, so this is implemented with method chaining. Same example in C++ looks like:

large_motor m;
m.set_speed_regulation_enabled('on').set_speed_sp(750).run_forever();

I am not sure how this would look like in other languages, so I don't know if this should go into cross-language specification. Although it may worth it to at least ask for argument-less methods like run_forever or stop.

2. Batch set function. I liked the python keyword arguments approach so much I also implemented a standalone set method in python that is able to batch-set device parameters:

m.set(ramp_up_sp=300, ramp_down_sp=300, stop_command='brake')

Same thinking regarding putting this into specification as above applies here.

3. The steering function may be worth adding to the specification. It is modeled after the steering block in the original mindstorms software and computes how fast each motor in a pair should turn to achieve the specified direction change. It returns a pair of values corresponding to the left and the right motor power:

for (motor, power) in zip((left_motor, right_motor), steering(direction=50, power=900)):
    motor.run_forever(speed_sp=power)

4. The interfaces for ev3 buttons, sound, LCD. These are not yet in specification and I think they belong there. The classes in C++ were introduced by @fdetro, I mostly just exposed them in python, with the exception of LCD class, which uses python image library to provide some drawing primitives for the ev3 screen. I borrowed the idea from @topikachu's implementation. May be we should put some thought into making the interfaces generic enough to be cross-language-implementable.

I am out of other ideas for now, but I think we should ping authors of actively developed third-party libraries. @topikachu, @theZiz, @in4lio?

WasabiFan commented 9 years ago

I like all of those, and they should be pretty easy to implement. I have some ideas for implementing in JS/node (I think passing object literals should work well in place of keyword arguments, maybe with support for chaining as well). Because at least the first two items are very language-specific, I think I'll work it into the spec as a note without a specific explanation of how it works syntactically.

On the subject of buttons, sound, and the LCD, @fdetro and I were discussing this early on, but never came to a decision on specifics of these implementations. The main discussion was around the buttons, where one really wants to expose events as well as single-time checking. Have you added event-driven APIs, or just checking for whether the button is pressed?

Past the buttons, the sound and LCD are fairly standard behavior. Most direct framebuffer manipulation libraries will work with ev3dev (as I understand it, anyway) and the sound is the same. So, I think that instead of re-implementing that code, we should have recommendations with each library that gives links to sound and display libraries that are compatible with that language. If there are ev3dev-specific utilities that are needed like things to allocate the virtual terminals, that would be helpful to expose in our libraries. How does that sound?

I'll start working on adding notes about motor and batch-setter helper functions into the spec and implementing it in JS.

WasabiFan commented 9 years ago

Currently, we also don't have dedicated classes for types of sensors listed in the spec. Which sensors do you think we should add here, and what properties should they have? I think this can mostly be extended from what is already implemented in C++/Python.

WasabiFan commented 9 years ago

@ddemidov am I correct that in your implementation the steering function just computes and returns the motor values and requires that the motors be set manually afterward? What was the motivation for this design? I think we should consider a "motor pair" class that has a method to steer a pair of motors, or maybe even ask for that to be considered for implementation at the driver level.

ddemidov commented 9 years ago

Have you added event-driven APIs, or just checking for whether the button is pressed?

I have not added the API, but I think this is a great idea. I'll look into this. I think it should be done similarly to what is currently implemented for remote control buttons (and, by the way, we did not speak about the remote control yet).

Regarding the sound, I think we could expose some simple functionality that is available from standard software: play a tone, play a sound file. Since patched espeak utility is available on ev3, I think we should also allow using it. Same goes for other ev3dev-specific utilities.

I agree that LCD utilities should be covered by language-specific libraries.

am I correct that in your implementation the steering function just computes and returns the motor values and requires that the motors be set manually afterward?

That is correct. It did started as one-function-does-all kind of thing, but that was before the interface with keyword arguments was introduced, and a lot of functionality was duplicated with the single motor drive function. Besides, I have hit a couple of cases where I wanted to treat the motors in the pair slightly differently. For example, one motor should rotate until stalled or until a specified position, while the other should stop at the same moment. I found it was easier to just have a function that would compute the power for each of the motors and then deal with the motors individually. I agree that introducing a Tank class that would hold both motors and allow easy steering is a good idea, but I would still expose the standalone steering() function (and use it inside the Tank implementation).

WasabiFan commented 9 years ago

Regarding the sound, I think we could expose some simple functionality that is available from standard software: play a tone, play a sound file. Since patched espeak utility is available on ev3, I think we should also allow using it. Same goes for other ev3dev-specific utilities.

Sounds good. I'll take a look at our options and try to propose an API structure for this (which will probably follow anything that is already implemented in C++).

That is correct...

That makes sense. I'll add a steering-compute function to the spec, and then we can look into an end-to-end implementation if we decide that's needed.

I have added motor helper functions and a few other things to my local copy of the JS repo and will commit/push when that is in a reasonable and tested state. Thanks for guiding these API decisions!

ddemidov commented 9 years ago

Currently, we also don't have dedicated classes for types of sensors listed in the spec. Which sensors do you think we should add here, and what properties should they have?

The list of sensors currently explicitly implemented may be found in python docs here: http://ddemidov.github.io/ev3dev-lang-python/#sensors. These mostly are just convenience classes that allow easier construction than providing a driver name to the generic sensor class. The only exception is i2c_sensor which additionally provides fw_version() and poll_ms() methods.

I think all sensors from standard kits like EV3 home/education (and may be also from older NXT kits) should be in the specification. If a full list of supported sensors is available from somewhere (I think @dlech spoke about some json files at some point), then we could auto-generate our specification and the bindings.

ddemidov commented 9 years ago

Also, we do have some sensors in the spec.json. These were added to provide a documented list of possible property values for each of the sensors.

ddemidov commented 9 years ago

As it was pointed out in #29, #59, ddemidov/ev3dev-lang-python#8, we should add lego-port class to the specification.

WasabiFan commented 9 years ago

@ddemidov I agree, given that it's pretty much required in all instances on the raspi as well as some special cases on the EV3 brick. What are your thoughts on implementation details? I'd be happy to implement it on my end if you can write it up in the spec.

Personally, I have been having trouble recently grappling with the increasingly large list of things I have to get done, on top of my various open ev3dev projects. Yesterday I spent some time and cleaned up my Node.js implementations of the above features, but still haven't gotten it in a state where I'm ready to commit it. I hope to get that done within a day or two, and might be able to add the port class as well.

P.S. I completely forgot about the steering/sound topics as I started work on the other enhancements. I might be able to get that written out soon, but if you want to expedite the process and write out a generalized version of what's in the Python implementation that would be appreciated. I should be able to spend more time on this in the coming weeks.

ddemidov commented 9 years ago

I'd be happy to implement it on my end if you can write it up in the spec.

I'll try to make a pull request for the specification of the lego-port class in the coming days. It should be straightforward.

but if you want to expedite the process and write out a generalized version of what's in the Python implementation that would be appreciated

I'll look into this as well, but not sure how soon.

WasabiFan commented 9 years ago

@ddemidov I just pushed my JS implementation of batch setters and the motor command helper functions. Working on lego-port next.