Code Monkey home page Code Monkey logo

ev3dev-lang-python's Introduction

Python language bindings for ev3dev

https://travis-ci.org/ev3dev/ev3dev-lang-python.svg?branch=ev3dev-stretch Documentation Status Chat at https://gitter.im/ev3dev/chat

A Python3 library implementing an interface for ev3dev devices, letting you control motors, sensors, hardware buttons, LCD displays and more from Python code.

If you haven't written code in Python before, you can certainly use this library to help you learn the language!

Getting Started

This library runs on ev3dev. Before continuing, make sure that you have set up your EV3 or other ev3dev device as explained in the ev3dev Getting Started guide. Make sure you have an ev3dev-stretch version greater than 2.2.0. You can check the kernel version by selecting "About" in Brickman and scrolling down to the "kernel version". If you don't have a compatible version, upgrade the kernel before continuing.

Usage

To start out, you'll need a way to work with Python. We recommend the ev3dev Visual Studio Code extension. If you're interested in using that, check out our Python + VSCode introduction tutorial and then come back once you have that set up.

Otherwise, you can can work with files via an SSH connection with an editor such as nano, use the Python interactive REPL (type python3), or roll your own solution. If you don't know how to do that, you are probably better off choosing the recommended option above.

The template for a Python script

Every Python program should have a few basic parts. Use this template to get started:

#!/usr/bin/env python3

from time import sleep

from ev3dev2.motor import LargeMotor, OUTPUT_A, OUTPUT_B, SpeedPercent, MoveTank
from ev3dev2.sensor import INPUT_1
from ev3dev2.sensor.lego import TouchSensor
from ev3dev2.led import Leds

# TODO: Add code here

The first line should be included in every Python program you write for ev3dev. It allows you to run this program from Brickman, the graphical menu that you see on the device screen. The other lines are import statements which give you access to the library functionality. You will need to add additional classes to the import list if you want to use other types of devices or additional utilities.

You should use the .py extension for your file, e.g. my-file.py.

If you encounter an error such as /usr/bin/env: 'python3\r': No such file or directory, you must switch your editor's "line endings" setting for the file from "CRLF" to just "LF". This is usually in the status bar at the bottom. For help, see our FAQ page.

Important: Make your script executable (non-Visual Studio Code only)

To be able to run your Python file, your program must be executable. If you are using the ev3dev Visual Studio Code extension, you can skip this step, as it will be automatically performed when you download your code to the brick.

To mark a program as executable from the command line (often an SSH session), run chmod +x my-file.py.

You can now run my-file.py via the Brickman File Browser or you can run it from the command line by preceding the file name with ./: ./my-file.py

Controlling the LEDs with a touch sensor

This code will turn the LEDs red whenever the touch sensor is pressed, and back to green when it's released. Plug a touch sensor into any sensor port before trying this out.

ts = TouchSensor()
leds = Leds()

print("Press the touch sensor to change the LED color!")

while True:
    if ts.is_pressed:
        leds.set_color("LEFT", "GREEN")
        leds.set_color("RIGHT", "GREEN")
    else:
        leds.set_color("LEFT", "RED")
        leds.set_color("RIGHT", "RED")
    # don't let this loop use 100% CPU
    sleep(0.01)

If you'd like to use a sensor on a specific port, specify the port like this:

ts = TouchSensor(INPUT_1)

Heads-up: If you are using a BrickPi instead of an EV3, you will need to manually configure the sensor. See the example here: https://github.com/ev3dev/ev3dev-lang-python-demo/blob/stretch/platform/brickpi3-motor-and-sensor.py

Running a single motor

This will run a LEGO Large Motor at 75% of maximum speed for 5 rotations.

m = LargeMotor(OUTPUT_A)
m.on_for_rotations(SpeedPercent(75), 5)

You can also run a motor for a number of degrees, an amount of time, or simply start it and let it run until you tell it to stop. Additionally, other units are also available. See the following pages for more information:

Driving with two motors

The simplest drive control style is with the MoveTank class:

tank_drive = MoveTank(OUTPUT_A, OUTPUT_B)

# drive in a turn for 5 rotations of the outer motor
# the first two parameters can be unit classes or percentages.
tank_drive.on_for_rotations(SpeedPercent(50), SpeedPercent(75), 10)

# drive in a different turn for 3 seconds
tank_drive.on_for_seconds(SpeedPercent(60), SpeedPercent(30), 3)

There are also MoveSteering and MoveJoystick classes which provide different styles of control. See the following pages for more information:

Using text-to-speech

If you want to make your robot speak, you can use the Sound.speak method:

from ev3dev2.sound import Sound

sound = Sound()
sound.speak('Welcome to the E V 3 dev project!')

More Demo Code

There are several demo programs that you can run to get acquainted with this language binding. The programs are available at this GitHub site.

You can also copy and run the programs in the utils directory to understand some of the code constructs to use the EV3 motors, sensors, LCD console, buttons, sound, and LEDs.

We also highly recommend ev3python.com where one of our community members, @ndward, has put together a great website with detailed guides on using this library which are targeted at beginners. If you are just getting started with programming, we highly recommend that you check it out at ev3python.com!

Using Micropython

Normal Python too slow? Review Micropython to see if it supports the features your project needs.

Library Documentation

Class documentation for this library can be found on our Read the Docs page. You can always go there to get information on how you can use this library's functionality.

Frequently-Asked Questions

Experiencing an odd error or unsure of how to do something that seems simple? Check our our FAQ to see if there's an existing answer.

ev3dev-lang-python's People

Contributors

251 avatar alesolano avatar amandaoneal avatar antonvh avatar bpmerkel avatar craigsammisutherland avatar ddemidov avatar dlech avatar drclick avatar dwalton76 avatar ensonic avatar ericpobot avatar fryfrog avatar gregcowell avatar heijmans avatar maxnoe avatar moriarty avatar nshenoy avatar omartin2010 avatar pepijndevos avatar remvee avatar rhempel avatar v-gar avatar vagoston avatar wasabifan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ev3dev-lang-python's Issues

alternative implementation proposal

Hi,

After playing a bit with autogen and templates to learn how they work, I'm still not really convinced of their real benefits.

Having experimented with the whole process of modifying Python binding code, including templates update, my gut feeling is that the gains obtained by automatic multiple languages source generation are not significant enough to compensate the hassles of templates coding. It is pretty tedious to write mixtures of templating code and Python (or whatever language) since both are mixed in a way which makes the result pretty unreadable, added to the fact that no editor or IDE can help you there.

In addition, having cross-language templates for code generation prevents from using features available in some of them only. For instance, Python mixins have no equivalent in Java, and thus cannot be used at class generation level. Depending on the languages, the implementation classes ideal architecture can be different if we want to use the most of what each language has to provide, which autogen mechanism makes quite difficult to achieve, if even possible.

And at the end of the day, it is still required to code a set of templates for each language, and these templates will have to be maintained by hand anyway.

I admit that changes such as device class peudo-files name changes can be propagated automatically when using autogen, but this is not enough for me to consider that the balance is on its side.

BTW I could note that it seems that the templates were not up to date at the time I tested, since the "pilot" file was not in coherence with the current sources organization (recent refactoring as a package). If even the creators bypass it and code directly the generated sources, what sceptical folks like me should think...

So I've made an attempt to completely remove templates and wrote an alternative version of the Python binding, heavily based on the current version of the autogen generated code. It is available at https://github.com/EricPobot/ev3dev-lang-python-alt.

In addition to the library code, the repo contains demonstration programs, including a complete robot for testing the usability from the application developer point of view (as requested some time ago).

I have also done some job at documentation level (adding missing parts, adding method parameter and result types,...).

Please let me know what you think about this work. I'm aware that my "rebel" way of doing could not be at your taste, since it seems that you stick to the autogen method, but I had to do it for making my own opinion ;) If the proposal were not approved to be merged in the official line, I think I'll try to maintain it on my side, keeping it aligned with the common API. Of course, it would be better not to have several parallel tracks ;)

Maybe I'm missing some important point WRT autogen benefits, which bias my evaluation. Please let me know.

Best regards

Eric

Cannot find the version number

python setup.py install
Traceback (most recent call last):
File "setup.py", line 7, in
version=git_version(),
File "/Users/big/j/ev3dev-lang-python/git_version.py", line 74, in git_version
raise ValueError("Cannot find the version number!")
ValueError: Cannot find the version number!

Screen().img got renamed to Screen()._img and is now also missing from the docs.

In open-roberta I was using this code to show image in the screen:

image = Image.frombytes('1', (178, 128), IMAGES[picture], 'raw', '1;IR', 0, 1)
lcd = ev3dev.Screen()
lcd.img.paste(image, (0, 0))
lcd.update()

I could fix this by now doing

- lcd.img.paste(image, (0, 0))
+ lcd._img.paste(image, (0, 0))

I can't find when that changed. Anyway this is not about blaming :) Can we expose this in a nicer way properly?

BrickPi Analog Sensors?

I try to get a touch sensor to work on the brickpi, but I'm a little lost. What Class should I use? Where is the sensor in /sys/class ?

>>> from ev3dev.auto import TouchSensor, INPUT_4
>>> ts = TouchSensor(INPUT_4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 1664, in __init__
    Device.__init__(self, self.SYSTEM_CLASS_NAME, name_pattern, name_exact, driver_name=['lego-ev3-touch', 'lego-nxt-touch'], **kwargs)
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 180, in __init__
    name = next(list_device_names(classpath, name_pattern, **kwargs))
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 123, in list_device_names
    for f in os.listdir(class_path):
OSError: [Errno 2] No such file or directory: '/sys/class/lego-sensor'
anton@ev3dev-rpi:~$ ls /sys/class/
backlight        graphics          iscsi_session    raw          thermal
bcm2708_vcio     hidraw            iscsi_transport  rfkill       tty
bcm2835-gpiomem  i2c-adapter       leds             rtc          uio
bdi              i2c-dev           lego-port        scsi_device  vc
block            ieee80211         mem              scsi_disk    vc-cma
bsg              input             misc             scsi_host    vc-mem
dc-motor         iscsi_connection  mmc_host         sound        vc-sm
devcoredump      iscsi_endpoint    net              spi_master   vchiq
dma              iscsi_host        power_supply     spidev       vtconsole
gpio             iscsi_iface       pwm              tacho-motor  watchdog

Screen: TypeError: integer argument expected, got float

>>> import ev3dev.ev3 as ev3
>>> s = ev3.Screen()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/dist-packages/python_ev3dev-0.6.0-py3.4.egg/ev3dev/core.py", line 2310, in __init__
    "white")
  File "/usr/lib/python3/dist-packages/PIL/Image.py", line 2030, in new
    return Image()._new(core.fill(mode, size, color))
TypeError: integer argument expected, got float

It works with integer division in core.py:Screen

<                 (self.fix_info.line_length * 8 / self.var_info.bits_per_pixel, self.yres),

---
>                 (self.fix_info.line_length * 8 // self.var_info.bits_per_pixel, self.yres),

python3: issue with __del__ when script terminates

After picking up Denis's 'Restore Python3 compatibility' fix,
with python3 I observed weird issue related to del behavior.

It could be related to some race condition when python3
goes down. In one case 'isabs' function from posixpath.py becomes
None. So on call chain triggered by Motor del -> stop ...
it fails. In other case see below 'open' function disappeared.

(ev3dev_py34)root@ev3dev:~/projects/v/test2# cat del_test.py
import ev3dev.ev3 as ev3
m = ev3.LargeMotor("outB")
exit()
(ev3dev_py34)root@ev3dev:~/projects/v/test2# python3 del_test.py
Exception ignored in: <bound method LargeMotor.__del__ of <ev3dev.core.LargeMotor object at 0xb6a14b30>>
Traceback (most recent call last):
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 221, in **del**
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 670, in stop
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 235, in command
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 178, in set_attr_string
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 166, in _set_attribute
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/posixpath.py", line 357, in abspath
TypeError: 'NoneType' object is not callable

With some slight variation with the test issue disappears:

(ev3dev_py34)root@ev3dev:~/projects/v/test2# cat del_test1.py
import ev3dev.ev3 as ev3
def main():
    m = ev3.LargeMotor("outB")
main()
(ev3dev_py34)root@ev3dev:~/projects/v/test2# python3 del_test1.py
(ev3dev_py34)root@ev3dev:~/projects/v/test2# cat del_test2.py
import ev3dev.ev3 as ev3
def main():
    m = ev3.LargeMotor("outB")
    exit()
main()
(ev3dev_py34)root@ev3dev:~/projects/v/test2# python3 del_test2.py
(ev3dev_py34)root@ev3dev:~/projects/v/test2# cat del_test3.py
import ev3dev.ev3 as ev3
m = ev3.LargeMotor("outB")

(ev3dev_py34)root@ev3dev:~/projects/v/test2# python3 del_test3.py
(ev3dev_py34)root@ev3dev:~/projects/v/test2# 

It seems that it could be races in the code in other case
'open' name disappeared:

(ev3dev_py34)root@ev3dev:~/projects/v/test2# python3 del_test.py
Exception ignored in: <bound method LargeMotor.__del__ of <ev3dev.core.LargeMotor object at 0xb6a2eb30>>
Traceback (most recent call last):
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 221, in **del**
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 670, in stop
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 235, in command
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 178, in set_attr_string
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 166, in _set_attribute
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 88, in write
  File "/root/.virtualenvs/ev3dev_py34/lib/python3.4/site-packages/python_ev3dev-0.5.0.post3-py3.4.egg/ev3dev/core.py", line 74, in file_handle
NameError: name 'open' is not defined

When the same tried with python2 everything looks fine.

By googling info about del I found this:

https://docs.python.org/2/reference/datamodel.html#object.__del__

The pink section pretty much explains the issues I observe,
which begs the question whether it is good idea to have del
method in the first place.

On one hand desire to stop all motors when cotrolling process exits,
especially abnormally, is well understood. But needless to say that
if above condition hit when motor was running it won't stop anyway.

I wonder whether ev3dev infra (file interface) can provide more solid
emergency stop mechanism. For example stop could be trigger on close
of some special file, like /sys/class/tacho-motor/motor?/emergency_stop.
If such file would be opened, ev3dev system will stop motor when file
closes. In this case python can just open the file in Motor contructor
and file will be automatically closed when python exists, that will
trigger motors stop. It would stop the motors even if process
explicitly killed.

Other language bindings can use the same mechanism.

How to make changes to ev3dev/core.py

Is it acceptable to make changes directly to ev3dev/core.py or should all changes be made via the templates? If the former how can I tell which sections can/cannot be modified? If the latter is if ok for me to add a helper.py (I'm not particular about the name) to that directory?

I have a Tank class that I would like to add that serves as a base class for TRACK3R.

shoudn't the bindings use their own commands

In the code I see a lot of cases like:

COMMAND_RUN_FOREVER = 'run-forever'
...
self.command = 'run-forever'

Shouldn't the impl use the constants? If okay, I'll send a PR to fix this,

"robot" user not created

The directives for demos providers say that they must ensure their code being able to run under the robot account, used by Brickman when starting programs.

This user has not been created during the installation, done with the latest archive available at that time (2015-09-13). There is no corresponding home dir, and it is not present in /etc/passwd neither.

Browsing the Brickman code, it seems that the user is ev3dev instead (FileBrowserController.vala:31 and FileBrowserController.vala:90).

leds api defunct (for root)

Previously I could do:

ev3dev.led.orange_on()

later this got changed to

ev3dev.Led.orange_on()

and now it is supposedly

ev3dev.Leds.orange_on()

but it does not exist. There seems to be no wait to set both leds in one call anymore? Instead I seem to have to do

ev3dev.Leds.set_color(ev3dev.Leds.LEFT, ev3dev.Leds.ORANGE)

but that is broken:

ev3dev.Leds.set_color(ev3dev.Leds.LEFT, ev3dev.Leds.ORANGE)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "ev3dev/ev3.py", line 76, in set_color
    l.brightness_pct = v * pct
  File "ev3dev/core.py", line 1688, in brightness_pct
    self.brightness = value * self.max_brightness
  File "ev3dev/core.py", line 1606, in max_brightness
    return self.get_attr_int('max_brightness')
  File "ev3dev/core.py", line 169, in get_attr_int
    return int(self._get_attribute(attribute))
  File "ev3dev/core.py", line 162, in _get_attribute
    return self._attribute_cache.read(abspath(self._path + '/' + attribute))
  File "ev3dev/core.py", line 82, in read
    f = self.file_handle(path)
  File "ev3dev/core.py", line 74, in file_handle
    f = open(path, mode, 0)
IOError: [Errno 13] Permission denied: '/sys/class/leds/ev3-left0:red:ev3dev/max_brightness'

Make sure Python 3 version of Debian package is installed in ev3dev image

In the current ev3dev image (ev3-ev3dev-jessie-2015-12-30) env3dev is not importable from python3:

robot@ev3dev:~$ python3
>>> import ev3dev
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'ev3dev'
>>> 

With python2 importing works. Ideally this should work identically for either Python version.

See topikachu/python-ev3#63 for step-by-step instructions to reproduce the issue.

file handle cache breaks sensors

try this in python (with sensor 0 being the touch sensor):

f = open("/sys/class/lego-sensor/sensor0/value0", "r")
print f.readline()
0

f.seek(0)
print f.readline()
0

ev3 leds implementation

I am thinking of adding predefined instances for ev3 leds. Something along these lines right after the usual led class declaration:

led.red_left    = led(name='ev3-left0:red:ev3dev')
led.red_right   = led(name='ev3-right0:red:ev3dev')
led.green_left  = led(name='ev3-left1:green:ev3dev')
led.green_right = led(name='ev3-right1:green:ev3dev')

I think though @rhempel would suggest that we put the names into autogen/spec.json and use it to generate the above code. Hence the question: we in principle should support both EV3 and RPI, and I guess RPI features different set of leds. How do we deal with this in specification?

Transition from boostc to pure-python

I think we are now feature complete w.r.t. boostc version (pinging @ensonic). We can push this to PyPI and advertise on ev3dev.org.

Now, python-ev3dev package name on PyPI is taken by boostc version. The latest version published there was 0.2.2. I suggest we tag the pure-python bindings with something like 0.3 and just keep pushing to the same package on PyPI. This way users may still download older (boosts-based) versions. And I am going to put deprecation warning with a link to this repo in boostc version README.

module organization (second take)

Forewords: if this is not the right place for such discussions, please let me know and tell me the right way to continue it.

I'd like to share my views WRT this topic. The current situation (i.e. the ev3dev.py module at the top level of system wide packages is IMHO far from ideal, since it will sooner or later be a problem if the library grows (and it will, because it's damn promising ;-))

The way I process for other projects, whatever size and number of modules is this one :

+ my_awesome_package/
  + __init__.py
  + core.py

The initial content of __init__.py is:

from .core import *

Doing this, users can do a simple from my_awesome_package import * as if the library was a simple Python module located at the root of Python local lib.

I find this organization being cleaner, and above all, totally extensible. If offers the option of user the root package as a namespace, resulting in a better organization of the future additions.

Another point related to this is the way the different targets are presently managed. It is heavily based on code generation, but to be honest, I dislike it a lot, since not Pythonic at all (I've the feeling to be in C/C++ word with heavy pre-processor usage ;-) ). Take for instance the LED support which has been added recently. The way it is implemented is totally unfriendly with IDE hints mechanism, since it uses something close to Javascript prototype mechanism. I would have used the following approach :

  • put a LedBase root class in the core module of ev3dev library, containing cross-platform stuff
  • create a module per target, and implement there a concrete Led class adding the specificity of the real hardware

Application developers will have to do a simple from ev3dev.ev3 import Led.

The benefits I can see are:

  • no more code generation
  • pure Python, fully introspectable by IDEs and tools
  • clear separation of concerns (i.e. target platforms)

I can see no problem with the fact that there will be a Led concrete class in several modules, because an application will never mix them, since targeting a single one at a time.

Developing a multi-target application can be easily done with stances such as :

import config
if config.TARGET == 'BrickPi':
    from ev3dev.brickpi import Led
if config.TARGET == 'PiStorms':
    from ev3dev.pistorms import Led
else:
    # fall back to EV3 by default
    from ev3dev.ev3 import Led

I have not analyzed ev3dev.py module in detail enough, and I suspect that code generation is probably unavoidable in some circumstances, but IMHO a part of it could be avoided by using the proposed architecture, and the resulting code would be easier to understand by users and maintained by contributors (I don't feel myself very comfortable at this time with the code generator stuff, and will avoid it as much as I can in my works).

Don't misinterpret my words : I'm not criticizing what has been done, which is amazing because of the perspectives it opens. I just try to provide some feedback and ideas.

Things to do to catch up with boostc

  • Implement device_index property for Device class.
  • Implement platform-specific Led instances and color functions.
  • Implement measured_amps and measured_volts properties for PowerSupply class (the names in the generated doc seem to be messed up).
  • Implement Button class for ev3 buttons.
  • Implement Sound class.
  • Implement LCD class.
  • Implement RemoteControl class.
  • Implement bin_data_format and bin_data for Sensor.
  • Implement steering function.

sound.tone is broken

from ev3dev import ev3 as ev3dev
ev3dev.Sound.tone(100,100).wait()
# or
ev3dev.Sound.tone([(100,100)]).wait()

this should only play one tone, but plays two instead. The beep command that is generated is '/usr/bin/beep -n -f 100 -l 100' while '/usr/bin/beep -f 100 -l 100' works. The bug is that '-n' should only be used for the next tone. PR coming.

Debian packaging todo

  • Add debian/copyright
  • Fix missing comma in setup.py
  • Add extended description to debian/control
  • Standards version should be 3.9.5 in debian/control
  • Remove RELEASE-VERSION from git and fix build

new project: ev3-mapping

Hello!

Some friends and I are working in a project with the goal of doing some mapping with the EV3. The project is called ev3-mapping and we use, of course, ev3dev and this Python library.

It's our first project with GitHub, Python, documentation and everything, so any advice or help is very welcomed!!


This weekend we'll be coding some classes that could be useful for everyone (or maybe they have already been created), like a class for any Differential Robot and other for a EXPLOR3R robot.

automatic platform detection should not be done in ev3dev package __init__

The automatic detection based on the current architecture makes impossible to have the appropriate imports done when working on the dev system and targeting something else than an EV3. When developing an app for a BrickPi for instance, IDE code hints, completion and checking mechanisms will not work since the ev3 import will always be done.

The platform dependant import should be left to the responsibility of the robot code developer, who is supposed to know which platform he targets. Instead of using ย import ev3dev in the application code modules, he will use something like form ev3dev import ev3.

To have this mechanism work properly platform specific modules must include from .core import *, so that the generic definitions will be made available automatically to them. BTW doing this makes possible for platform specific modules to override generic definitions by re-defining them if needed.

easy_install issues: arm-linux-gnueabi-gcc' failed with exit status 1

As I install from source, this is not an issue for me, but others may want to look at this

dpkg-reconfigure tzdata

apt-get update
apt-get updateapt-get upgrade
apt-get upgrade
apt-get dist-upgrade
reboot

apt-get install git
apt-get install ipython-notebook
apt-get install libboost-python1.55.0 python-setuptools python-pil

easy_install -U python-ev3dev

Searching for python-ev3dev
Reading https://pypi.python.org/simple/python-ev3dev/
Best match: python-ev3dev 0.4.2
Downloading https://pypi.python.org/packages/source/p/python-ev3dev/python-ev3dev-0.4.2.tar.gz#md5=a02c7785adf40b2adbb23775435974de
Processing python-ev3dev-0.4.2.tar.gz
Writing /tmp/easy_install-a7xReP/python-ev3dev-0.4.2/setup.cfg
Running python-ev3dev-0.4.2/setup.py -q bdist_egg --dist-dir /tmp/easy_install-a7xReP/python-ev3dev-0.4.2/egg-dist-tmp-uLkYle
file ev3dev.py (for module ev3dev) not found
file ev3dev.py (for module ev3dev) not found
file ev3dev.py (for module ev3dev) not found
warning: install_lib: 'build/lib.linux-armv5tejl-2.7' does not exist -- no Python modules to install

zip_safe flag not set; analyzing archive contents...
Adding python-ev3dev 0.4.2 to easy-install.pth file

Installed /usr/local/lib/python2.7/dist-packages/python_ev3dev-0.4.2-py2.7.egg
Processing dependencies for python-ev3dev
Searching for pil
Reading https://pypi.python.org/simple/pil/
Reading http://effbot.org/downloads/#Imaging
Reading http://effbot.org/zone/pil-changes-115.htm
Reading http://www.pythonware.com/products/pil
Best match: PIL 1.1.7
Downloading http://effbot.org/media/downloads/PIL-1.1.7.tar.gz
Processing PIL-1.1.7.tar.gz
Writing /tmp/easy_install-5M64tm/PIL-1.1.7/setup.cfg
Running PIL-1.1.7/setup.py -q bdist_egg --dist-dir /tmp/easy_install-5M64tm/PIL-1.1.7/egg-dist-tmp-2y1Ul4
WARNING: '' not a valid package name; please use only.-separated package names in setup.py
unable to execute 'arm-linux-gnueabi-gcc': No such file or directory
error: Setup script exited with error: command 'arm-linux-gnueabi-gcc' failed with exit status 1

led attributes might be out of sync with the kernel

On a ev3:

ls -al /sys/class/leds/ev3:left:red:ev3dev/
total 0
drwxr-xr-x 3 root root      0 Jan 21 09:43 .
drwxr-xr-x 6 root root      0 Jan  1  2000 ..
-rw-rw-r-- 1 root ev3dev 4096 Jan 21 09:08 brightness
lrwxrwxrwx 1 root root      0 Jan  1  2000 device -> ../../../leds_pwm
-r--r--r-- 1 root ev3dev 4096 Jan  1  2000 max_brightness
drwxr-xr-x 2 root root      0 Jan  1  2000 power
lrwxrwxrwx 1 root root      0 Jan  1  2000 subsystem -> ../../../../../class/leds
-rw-rw-r-- 1 root ev3dev 4096 Jan 21 09:08 trigger
-rw-rw-r-- 1 root ev3dev 4096 Jan  1  2000 uevent

but on the python api:

>>> dir(ev3dev.Led)
['DEVICE_ROOT_PATH', 'SYSTEM_CLASS_NAME', 'SYSTEM_DEVICE_NAME_CONVENTION', '_DEVICE_INDEX', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_get_attribute', '_matches', '_set_attribute', 'brightness', 'brightness_pct', 'delay_off', 'delay_on', 'device_index', 'get_attr_from_set', 'get_attr_int', 'get_attr_line', 'get_attr_set', 'get_attr_string', 'max_brightness', 'set_attr_int', 'set_attr_string', 'trigger', 'triggers']

The trigger attribute can be set, but if I e.g. try to do:

leds.set(ev3dev.Leds.RIGHT, trigger='timer', delay_on=500, delay_off=500)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/ev3dev/ev3.py", line 89, in set
    setattr(led, k, kwargs[k])
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 1763, in delay_off
    self.set_attr_int('delay_off', value)
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 210, in set_attr_int
    self._set_attribute(attribute, '{0:d}'.format(int(value)))
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 204, in _set_attribute
    self._attribute_cache.write(abspath(self._path + '/' + attribute), value)
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 91, in write
    f.write(value.encode())
IOError: File not open for writing

And indeed there are no 'delay_on/off' sys-fs entries. Maybe I am missing somethoing, if so we need more examples :)

PS 4 Controller via Bluetooth

Can I connect a PS4 DS4 Controller via Bluetooth with ev3dev? And with which commands can I check the values from the controller in Python?

python3 ValueError: can't have unbuffered text I/O

Hi,

I am a beginner in programming with python.
I installed ev3dev-lang-python for python3. When I try to run "motors = [LargeMotor(port) for port in (OUTPUT_B, OUTPUT_C)]" from autodrive.py in demo-folder I get:
ValueError: can't have unbuffered text I/O

How do I solve this problem?

motor commands not working

I was testing some motor commands. run-direct command and run_direct() function work fine. However, run-to-abs-pos and run-timed commands, along with run_to_abs_pos() and run_timed() functions, are not in the mood to work. (They don't throw any errors, they just do nothing).

These are my .py files. Hope I was using the functions properly.

#!/usr/bin/python

from ev3dev.auto import *

m = LargeMotor(OUTPUT_A)

m.position_sp = 360
m.run_to_abs_pos()
#!/usr/bin/python

from ev3dev.auto import *

m = LargeMotor(OUTPUT_A)

m.time_sp = 1000
m.run_timed()

Also, I don't know how to use position_p attribute. It always comes with this error.

>>> m.position_p
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 416, in position_p
    return self.get_attr_int('hold_pid/Kp')
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 207, in get_attr_int
    return int(self._get_attribute(attribute))
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 200, in _get_attribute
    return self._attribute_cache.read(abspath(self._path + '/' + attribute))
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 85, in read
    return f.read().decode().strip()
IOError: [Errno 95] Operation not supported

Thank you!

setup.py broken

python setup.py install fails with error : package directory 'ev3dev' does not exist

This is caused by the package directive still here while the module has been moved out of its original directory. This can be fixed by either substituting it with py_modules or moving the module back in a package, depending on the library organisation choice.

Trouble Using Motor Commands - "IOError: [Errno 13]"

So if I try to run the following program,

#!/usr/bin/env python

from time import sleep
from ev3dev.auto import *
m = LargeMotor(OUTPUT_D)
assert m.connected, "Missing motor in port D"
m.run_forever()
print("Hello!")

sleep(5)

the m.run_forever() throws this error:

Traceback (most recent call last):
  File "./pytests.py", line 8, in <module>
    m.run_forever()
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 630, in run_forever
    self.command = 'run-forever'
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 238, in command
    self.set_attr_string('command', value)
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 181, in set_attr_string
    self._set_attribute(attribute, "{0}".format(value))
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 169, in _set_attribute
    self._attribute_cache.write(abspath(self._path + '/' + attribute), value)
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 91, in write
    f = self.file_handle(path)
  File "/usr/lib/python2.7/dist-packages/ev3dev/core.py", line 77, in file_handle
    f = open(path, mode, 0)
IOError: [Errno 13] Permission denied: '/sys/class/tacho-motor/motor0/command'
Exception IOError: (13, 'Permission denied', '/sys/class/tacho-motor/motor0/command') in <bound method LargeMotor.__del__ of <ev3dev.core.LargeMotor object at 0xb678c030>> ignored

Does anyone have any idea what's going on here? When I run m.commands, run_forever is listed as a valid command. Also, when I run m.commands, I get an error that looks like this after the program has finished running:

Exception IOError: (13, 'Permission denied', '/sys/class/tacho-motor/motor0/comm          and') in <bound method LargeMotor.__del__ of <ev3dev.core.LargeMotor object at 0          xb67aa030>> ignored

Module organization

One thing I don't like is how the module is organized. When I write

from ev3dev import *

I expect to be able to write d = Device(). But now, since ev3dev module (the top folder) has the ev3dev submodule (the ev3dev.py file) I have to do d = ev3dev.Device(). Normally if I wanted that, I would just import ev3dev instead.

So I think we should keep just the ev3dev.py at the top level and get rid of the ev3dev folder with __init__.py.

Generic cache class

@rhempel started the discussion in #28, I think it deserves an issue of its own.

A couple of classes now have their own implementation of cache (basically just a dictionary). We could introduce generic class for cache. What bugs me is Device and Button use their caches a bit differently.

Device:

    def _attribute_file( self, attribute, mode, reopen=False ):
        """Manages the file handle cache and opening the files in the correct mode"""

        attribute_name = os.path.abspath( self._path + '/' + attribute )

        if attribute_name not in self.filehandle_cache:
            f = open( attribute_name, mode )
            self.filehandle_cache[attribute_name] = f
        elif reopen == True:
            self.filehandle_cache[attribute_name].close()
            f = open( attribute_name, mode )
            self.filehandle_cache[attribute_name] = f
        else:
            f = self.filehandle_cache[attribute_name]
        return f

Button:

    def _button_file(self, name):
        if name not in self.filehandle_cache:
            f = open( name, 'r' )
            self.filehandle_cache[name] = f
        else:
            f = self.filehandle_cache[name]
        return f

What should we move into the cache class? Just some key-value store (similar to dict), but with some added functionality like size limitation (like LRU cache)? Now, since each object instance has its own cache, there is probably no need to deal with size limitation.

Sensor.commands throws IOError with EPERM instead of EOPNOTSUPP as said in the docs.

s = ev3dev.TouchSensor(ev3dev.INPUT_1)
s.commands
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "build/bdist.linux-armv5tejl/egg/ev3dev/core.py", line 1183, in commands
  File "build/bdist.linux-armv5tejl/egg/ev3dev/core.py", line 187, in get_attr_set
  File "build/bdist.linux-armv5tejl/egg/ev3dev/core.py", line 184, in get_attr_line
  File "build/bdist.linux-armv5tejl/egg/ev3dev/core.py", line 165, in _get_attribute
  File "build/bdist.linux-armv5tejl/egg/ev3dev/core.py", line 79, in read
  File "build/bdist.linux-armv5tejl/egg/ev3dev/core.py", line 65, in file_handle
IOError: [Errno 13] Permission denied: '/sys/class/lego-sensor/sensor1/commands'

While the docs
http://python-ev3dev.readthedocs.org/en/latest/#ev3dev.Sensor.commands
say 'EOPNOTSUPP, this seems to not hold for python.

cat /sys/class/lego-sensor/sensor1/commands
cat: /sys/class/lego-sensor/sensor1/commands: Operation not supported

speed regulation naming

The Motor class defines a property "speed_regulation_enabled" while most documents and the sysfs use "speed_regulation". What's the reason for this naming scheme? I got confused while testing the wiki examples for the shell.

Elegant way of determining outputs?

In the boostc lib there was a property OUTPUT_A, which would return 'outA' on an Ev3 but the literal /dev path on a Brickpi, something with TTY. What is an elegant way of filling this property on ev3dev?

Color framebuffer modes

Well, it looks like this is going to be a bit more complicated than I though. PIL doesn't support arbitrary bits-per-pixel. The valid modes are listed here. So, when getting the mode, it needs to be something like self.var_info.bits_per_pixel == 1 and "1" or "RGB" here.

However, the color devices we are using are 16-bit RGB565. PIL doesn't have a mode that corresponds to this. "RGB" is 24-bit. So, self._img.tobytes is only going to work for 1bpp. There are a number of solutions for the 16bpp though. Stack Overflow has some suggestions and there is also the code used by the official PiStorms software. Any of those should do.

So, something like:

if self.var_info.bits_per_pixel == 1:
    self.mmap[:] = self._img.tobytes("raw", "1;IR")
elif self.var_info.bits_per_pixel == 16:
    self.mmap[:] = self._img_to_rgb565_bytes()
else:
    raise Exception("Not supported")

...for here.

issues with the new apis (compared to boost bindings)

= Button =

Nov 05 12:30:28 ev3dev openrobertalab.py[716]: File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
Nov 05 12:30:28 ev3dev openrobertalab.py[716]: self.run()
Nov 05 12:30:28 ev3dev openrobertalab.py[716]: File "/usr/bin/openrobertalab.py", line 111, in run
Nov 05 12:30:28 ev3dev openrobertalab.py[716]: if self.service.hal.isKeyPressed('back'):
Nov 05 12:30:28 ev3dev openrobertalab.py[716]: File "/usr/lib/python2.7/dist-packages/roberta/ev3.py", line 140, in isKeyPressed
Nov 05 12:30:28 ev3dev openrobertalab.py[716]: return getattr(self.key, key).pressed
Nov 05 12:30:28 ev3dev openrobertalab.py[716]: AttributeError: type object 'Button' has no attribute 'back'

Button.back vs. Button.backspace
I renamed this for now

Nov 05 12:34:03 ev3dev openrobertalab.py[742]: File "/tmp/NEPOprog.py", line 44, in <module>
Nov 05 12:34:03 ev3dev openrobertalab.py[742]: main()
Nov 05 12:34:03 ev3dev openrobertalab.py[742]: File "/tmp/NEPOprog.py", line 40, in main
Nov 05 12:34:03 ev3dev openrobertalab.py[742]: while not hal.isKeyPressed('any'): hal.waitFor(500)
Nov 05 12:34:03 ev3dev openrobertalab.py[742]: File "/usr/lib/python2.7/dist-packages/roberta/ev3.py", line 127, in isKeyPressed
Nov 05 12:34:03 ev3dev openrobertalab.py[742]: if getattr(self.key, key).pressed:
Nov 05 12:34:03 ev3dev openrobertalab.py[742]: AttributeError: 'property' object has no attribute 'pressed'

Button.pressed vs. Button.check_buttons ?
but that'd be repeating the name, since what else should be checked in a Button class.
Same issues with 'buttons_pressed' property on subclasses.

Also why is Buttons.any a property?

Nov 05 13:11:28 ev3dev openrobertalab.py[887]: Traceback (most recent call last):
Nov 05 13:11:28 ev3dev openrobertalab.py[887]: File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
Nov 05 13:11:28 ev3dev openrobertalab.py[887]: self.run()
Nov 05 13:11:28 ev3dev openrobertalab.py[887]: File "/usr/bin/openrobertalab.py", line 111, in run
Nov 05 13:11:28 ev3dev openrobertalab.py[887]: if self.service.hal.isKeyPressed('back'):
Nov 05 13:11:28 ev3dev openrobertalab.py[887]: File "/usr/lib/python2.7/dist-packages/roberta/ev3.py", line 134, in isKeyPressed
Nov 05 13:11:28 ev3dev openrobertalab.py[887]: return self.keys.check_buttons([key])
Nov 05 13:11:28 ev3dev openrobertalab.py[887]: TypeError: unbound method check_buttons() must be called with Button instance as first argument (got list instance instead)

ev3dev.button became ev3dev.Buttons

= Sound =
since this changed from sync (system) to async.
tone(a,b) becomes tone(a,b).wait()

= Motors =
.state is always []

I expect this to work (works with the boost bindings)

m=ev3dev.LargeMotor(ev3dev.OUTPUT_B)
m.run_to_rel_pos(speed_regulation_enabled='on', position_sp=1000)
while (m.state):
  print m.state

If you change while(m.state) to while(True), it prints [] even though the motor is running.

= Sensors =
.value() return 0

I expect this to work (works with the boost bindings)

s = ev3dev.TouchSensor(ev3dev.INPUT_1)
s.value()

Whether I hold the touch sensor button pressed ot not, it returns 0. Or another one:

s = ev3dev.UltrasonicSensor(ev3dev.INPUT_4)
while(True):
  print s.value()
  time.sleep(0.5)

This prints a static value (191) for me. If instead for any of the sensors I do:

watch -n0.1 cat /sys/class/lego-sensor/sensor*/value0

I see the values changing.

At this point I wonder how you verify the bindings?

Ps4 Controller

If I print the events Form the controller allthing is great, but the two Joysticks dont work. All the other buttons work.

Allow `import ev3dev` to get started

A simple import ev3dev doesn't do much at the moment, and remains silent. This import should do something obvious, e.g. import the submodules, or complain that this import should not be used.

Proposed Behavior / Implementation

File: ev3dev/init.py

"""
Python language bindings for ev3dev.
"""
__version__ = '0.6.0'

import ev3

Motivation

On a freshly installed ev3dev system the current behavior leads to confusion. See topikachu/python-ev3#63 for details.

0.4.2 does not install via easy_install

I was going in install 0.4.2 and copy the files form git head over to try the latest, but:

easy_install -U python-ev3dev
Searching for python-ev3dev
Reading https://pypi.python.org/simple/python-ev3dev/
Best match: python-ev3dev 0.4.2
Downloading https://pypi.python.org/packages/source/p/python-ev3dev/python-ev3dev-0.4.2.tar.gz#md5=a02c7785adf40b2adbb23775435974de
Processing python-ev3dev-0.4.2.tar.gz
Writing /tmp/easy_install-uljZzf/python-ev3dev-0.4.2/setup.cfg
Running python-ev3dev-0.4.2/setup.py -q bdist_egg --dist-dir /tmp/easy_install-uljZzf/python-ev3dev-0.4.2/egg-dist-tmp-8yhsFs
file ev3dev.py (for module ev3dev) not found
file ev3dev.py (for module ev3dev) not found
file ev3dev.py (for module ev3dev) not found
warning: install_lib: 'build/lib.linux-armv5tejl-2.7' does not exist -- no Python modules to install

zip_safe flag not set; analyzing archive contents...
Removing python-ev3dev 0.3.0 from easy-install.pth file
Adding python-ev3dev 0.4.2 to easy-install.pth file

Installed /usr/local/lib/python2.7/dist-packages/python_ev3dev-0.4.2-py2.7.egg
Processing dependencies for python-ev3dev
Searching for pil
Reading https://pypi.python.org/simple/pil/
Reading http://effbot.org/downloads/#Imaging
Reading http://effbot.org/zone/pil-changes-115.htm
Reading http://www.pythonware.com/products/pil
Best match: PIL 1.1.7
Downloading http://effbot.org/media/downloads/PIL-1.1.7.tar.gz
Processing PIL-1.1.7.tar.gz
Writing /tmp/easy_install-3vY4gV/PIL-1.1.7/setup.cfg
Running PIL-1.1.7/setup.py -q bdist_egg --dist-dir /tmp/easy_install-3vY4gV/PIL-1.1.7/egg-dist-tmp-sPOQgs
WARNING: '' not a valid package name; please use only.-separated package names in setup.py
unable to execute 'arm-linux-gnueabi-gcc': No such file or directory
error: Setup script exited with error: command 'arm-linux-gnueabi-gcc' failed with exit status 1

`core.ButtonBase` misses `buttons_pressed` definition

The property is referenced in several methods of the ButtonBase class but it is defined in ButtonEVIO which is a subclass of it.

It works for now since the concrete classes seem to use ButtonEVIO (at list in the EV3 variant).

In ButtonBase, we should add something like:

@property
def buttons_pressed(self):
    return []

or better IMHO (since ButtonBase is supposed to be an abstract class):

@property
def buttons_pressed(self):
    raise NotImplementedError()

Nxt Compass sensor shows bad values

bin_data_format shows signed 8bit number and
expected values vs returned by value() function
0=0, 90=around 56, 180= around 124, 270= around -104

Values are from 0-127 then jump to -128 and from there to -77 and then back to 0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.