Git Product home page Git Product logo

simple-pid's Introduction

simple-pid

Tests PyPI Read the Docs License Downloads Code style: black

A simple and easy to use PID controller in Python. If you want a PID controller without external dependencies that just works, this is for you! The PID was designed to be robust with help from Brett Beauregards guide.

Usage is very simple:

from simple_pid import PID
pid = PID(1, 0.1, 0.05, setpoint=1)

# Assume we have a system we want to control in controlled_system
v = controlled_system.update(0)

while True:
    # Compute new output from the PID according to the systems current value
    control = pid(v)
    
    # Feed the PID output to the system and get its current value
    v = controlled_system.update(control)

Installation

To install, run:

python -m pip install simple-pid

Documentation

Documentation, including a user guide and complete API reference, can be found here.

Tests

This project has a test suite using pytest. To run the tests, install pytest and run:

pytest -v

License

Licensed under the MIT License.

simple-pid's People

Contributors

angel-ayala avatar dependabot[bot] avatar eirinnm avatar gonzalo-bulnes avatar ihornehrutsa avatar kmodexc avatar m-lundberg avatar mrakitin avatar rnestler avatar yasu31 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

simple-pid's Issues

port to CircuitPython

Not an issue, but just a question.

Is there any chance someone would be willing to port this to CircuitPython for use with adafruit boards? There currently is no PID library available for CircuitPython (or even micropython that I can find) and I think that it would be great to have your library available to circuitpython compatible microcontrollers. I actually tried myself by using mpy cross and I successfully compiled a .mpy but the resulting library fails to create an instance with:

import pid pid = PID(1, 0.1, 0.05, setpoint=1)

I'm sure there are many other CircuitPython users that would like to use your library as it is very easy to use, and currently would be the only go-to solution.

Thank you,
Mike G

Use output_limits setter in __init__() rather than setting the elements manually

In PID.__init__(), the output_limits setter should be used rather than setting self._min_output and self._max_output directly. As it is now, the checks done in the setter (min < max etc.) are not done if setting the limits through __init__(), so the values can be weird.

It should also be done after the call to self.reset() so that the integral term is clamped properly from the beginning.

Drop Python 2.7 and <3.6 support?

In 9900198 CI was changed to only test with Python > 3.6.

So would it make sense to drop support for Python 2.7 and Python < 3.5 completely? This would allow / need the following things:

I was wondering if the derivative gain should be negative

Hi guys,

First of all, great job putting this together. I was wondering though, why in line 127:

self._derivative = -self.Kd * d_input / dt

you set the derivative to negative. Is this intended? If so, why? The code you reference:

http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/

does not do this:

double dErr = (error - lastErr) / timeChange;
/*Compute PID Output*/
Output = kp * error + ki * errSum + kd * dErr;

Maybe I am wrong, but I would much appreciate it if you could took a look at it. I am currently implementing it with a power supply and a temperature readout. I was trying to tune the kp, ki and kd using the Ziegler-Nichols method and I noticed that setting kd != 0 introduces some steady overshoot.

Documentation update

The documentation on read the docs could use an update to look more modern and clean. And a general overhaul to make sure it works correctly, since it hasn't seen much love since it was first set up.

Also, the projects readme has grown quite a bit. I think it makes sense to move a lot of it into a dedicated user guide in the docs instead of keeping everything in the readme.

Question: Positive/Negative outputs

Hi,

I would like to request clarification in the documentation on whether or not the Simple PID can be used for dual-controls (e.g. heating/cooling). If it is already set up to do that, please explain how (positive/negative output values?)

usage question

Hello everyone!

Is there any more detailed usage example?

Let's say, I have a car with a range sensor, which gives me the distance to the wall, and I have the desired distance, so according to an error I send different PWM values to motors.

How the code would look like?

Thanks.

Run mypy in CI

As mentioned in #50 , mypy --strict simple-pid should be run in CI to avoid issues with typing annotations slipping by unnoticed.

Is it possible to use variable inputs?

Hello, i'm new to your PID-library. It works just fine with an constant input. Now I want to figure out how to make this controller work with variable inputs like ramps. Just restarting the PID in a timed loop won't work for the I-and D-values.
Is there already a possibility to feed an array of setpoints (for example a temperature curve) to the controller?
Thanks in advance
jwagn

mypy error when using `from simple_pid import PID`

When I use from simple_pid import PID and check the code with mypy --strict I get the following error:

$ mypy --strict test.py
test.py:1: error: Module "simple_pid" does not explicitly export attribute "PID"; implicit reexport disabled

I guess this is an issue with the from .PID import PID in __init__.py? If I change it to from .PID import PID as PID it works.

Also I think it is strange that the import in __init__.py shadows the PID module in simple_pid.

Maybe it would be better to rename the module to pid?

Document reverse acting control using simple_pid

Dear All,

Really more of a support question, but can the documentation be enhanced to show how to use simple_pid for reverse acting control?

To add colour: I have a temperature control (aiming for 70°C) for which I control the motor speed (PWM). Lower flow means higher temperatures, higher flow means lower temperatures.

Kees Jan

running the code and the simple provided example issue

I am going to use simple-pid algorithm.
I have installed simple-pid, however, according to the script below I need to have a “controlled_system” that I am not sure what it is. I am wondering if you could help me with that.

############################################################
from simple_pid import PID
pid = PID(1, 0.1, 0.05, setpoint=1)

Assume we have a system we want to control in controlled_system

v = controlled_system.update(0)

while True:
# Compute new output from the PID according to the systems current value
control = pid(v)

# Feed the PID output to the system and get its current value
v = controlled_system.update(control)

###########################################################
Also, I tried to figure out the algorithm through the water_boiler example, and for that one, I could not rerun it.
I would appreciate it if you could help.

Time module / micropython running on Pi Pico

The PID controller works since #63 on micropython/pi pico. The only problem is that pi pico only delivers seconds as int when calling time.time(). So the minimum sample rate is 1 second.
I solved the problem, but since I'm new to git, I was not able to Pull request.
The file where the changes were made is attached.
pid.txt

Implementation is incorrect

Hi, take a look at this cartpole example, it's cant solve it (actually i tried 100000 coefficients, didn't work):

import numpy as np
import gym
from simple_pid import PID

def sigmoid(x):
    return 1.0 / (1.0 + np.exp(-x))

env = gym.make('CartPole-v1')

pid = PID(0.9, 0.1, 0, setpoint=0, sample_time=0.00001)

for i_episode in range(20):
    state = env.reset()
    integral = 0
    derivative = 0
    prev_error = 0
    for t in range(500):
        env.render()
        print("state: ", state)
        control = pid(state[2])
        print("control: ", control)
        action = sigmoid(control)
        print("action: ", action)
        action = np.round(action).astype(np.int32)
        print("action: ", action)
        state, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break
env.close()

Preferred contribution method? Augmentation and error found

Hi,

I couldn't find a better way to contact you, so doing this. First, thank you for this, it's a good library that I was able to work into my project with ease. In digging in, I found an error in the implementation of the return value as it pertains to the Ki handling. I also implemented a Ki windup protection outside the pid.outside_limits value (that is, perhaps you don't want the final I component exceeding a value equal to that of the final return value). If you prefer to write your own, I can point out what I did, or let me know if you just want a PR filed. If needed, my contact is on my GH page.

Thanks!

-Aaron

Question about PID output

I have a simple use case where I've got a power supply controlling a peltier. The input + setpoint is the temperature I want, and the output of the PID should correspond directly (or proportionally) to the voltage I want to set.

At the moment, I ended up with something like

from simple_pid import PID
pid = PID(-0.5*0.20, -0.4*0.5/24, -0.066*0.5/24, setpoint=15)
pid.proportional_on_measurement = True
pid.sample_time = 1.0
pid.output_limits = (0, 5)

try:
    while True:
        v = ps_peltier.measureVoltage()
        t = get_temperature()
        control = pid(t)
        print(f"{t:0.4f} °C ({v:0.4f} V) -> {control:0.4f} V")
        ps_peltier.setVoltageLevel(control)
        time.sleep(pid.sample_time)
except KeyboardInterrupt:
    ps_peltier.setVoltageLevel(0.0)

where I just tried the Zeigler-Nichols method, and wanted it to stabilize at 15C. It seems to work, and I restricted the outputs from (0,5). The question is -- what is the normal procedure of scaling or remapping the output? Is it just enough to do this? If I wanted to control something that went from (0, 10) instead, or keeping (0,5) but mapping to (1,6) -- where it's linearly mapped, should I just map it outside of the PID control block, or should the PID block always be feeding the output back into the control at a 1:1 mapping?

tag next version?

Can you please tag another version? The version the documentation talks about is not what you get by installing the module (following the same documentation). Specifically, the 'error_map' argument is not in the latest v0.2.4

Auto_Mode toggling causes disturbance

Hi,

Firstly, great tool, thank you!

I have been working on implementing the controller and I think I've come across an unintended bug in the code when it comes to toggling "auto_mode" off and on again.

The issue arises for two reasons:

self._last_time is not updated during calls that take place while auto_mode is off, leading to a potentially huge dt term once auto_mode is re-enabled.

The self._error_sum is reset to 0 when auto_mode is re-enabled. I think this should be reset to whatever the last output was set to (possibly in manual mode) to ensure the control begins again as though it never stopped being in control. Lets say in manual mode I've changed my output and my input (PV) has settled at a new value. If I re-enable auto_mode having changed the setpoint to match my stable input value, then my derivative and proportional terms will be zero (proportional because error=0, derivative because d_input reset to 0 via _last_input being reset to None).
In order for the output to hold (the intended behaviour presumably), the error_sum term must be set to my previous output value thus mimicking the state of the controller if it had been responsible for the new stable input value. (Apologies if that isn't clear).

I've implemented the above changes and have successfully removed the "kick" that I was seeing upon re-enabling auto_mode. Let me know your thoughts.

Best,

James

Using PID to monitor/correct Xtal frequency wrt other/reference system.

I have a project for an Open-Source LTC box, similar to Lock-it or Tenticle-Sync. Multiple boxes communicate 'time' with an audio signal and then are expected to remain in sync. The issue I have is the the Pico's clock is not precision, and I want to add some synchronization method....
https://github.com/mungewell/pico-timecode

The basics are that each box is effectively a cascade counter, implemented in the PIO blocks, which count according to the PIO clock divider. I have already implemented a way to adjust the divider, and to monitor the timing difference between 'local' LTC and that received from the reference. This kind of looks like this....

clock_adjust

When monitoring the moment each frame (local vs reference) starts I get a 'delta time' (in us). I tried feeding this into a PID instance, expecting the output to produce a 'correction' value which would stabilize over time to a non-zero value...

Q. Is this correct thinking? - because I couldn't get it to work like that.... it never seems to settle.

It's worth noting that the measured time value is from the local clock, so it would appear that the reference is wrong... but is in-fact the correct one.

When starting a session the units are 'Jam Synced' together; which gets the clocks and phase the same. After some time they will drift apart. I believe that if the clock rate(s) are the same, then we will not need to monitor/correct the phase as it will just be correct.

ZeroDivisionError: float division by zero

I am trying to use this on a list here is my code:

pr = ['list of some values']
pid = PID(1, 0.5, 0, setpoint=1, output_limits=(0, 1), sample_time=None)
pid.set_auto_mode(True, last_output=0.5)
vfdp = []
for i in pr:
print(i)
vfdp.append(pid(i))

and it gives me zero division error as follows:

self._derivative = -self.Kd * d_input / dt

ZeroDivisionError: float division by zero

Proportional on measurement

Hey,
I'm not quite sure if this is a code issue, or if the problem is sitting in front of the keyboard.
Anyway, I want to use a simple PID to control control a resistive heater via PWM on a raspberry pi.
In the "normal", proportional-on-error mode, everything works fine.
However, using proportional-on-measurement = True, I for the life of me cannot get the P-term to become negative (checking with print(pid.components)). This seems to be caused by my output limits of [0,100] (which are the limits for the PWM control).
From what I understand from the last graph here:
http://brettbeauregard.com/blog/2017/06/introducing-proportional-on-measurement/
the P term is supposed to go negative.
Granted, I could change the output limits, but from what I understand, the limits should only affect the I-term. Also, the P-term goes negative just fine in the "normal" proportional-on-error mode.

From the above link, I gathered that the same tuning parameters should work for both modes with similar results. Yet neither those parameters nor any other (extremely large/small) values work.

Is this limiting of the P-term intended?
Or am I doing something wrong?
Thanks

pid.differential_on_measurement/differetial_on_measurement not working

Hello,

The pid doesn't detect pid.differetial_on_measurement=False and if I put it in the PID init, pid = PID(1, 0.8, 0.04, setpoint=5, output_limits=(-5, 5), differetial_on_measurement=False), I get the following error :
__init__() got an unexpected keyword argument 'differetial_on_measurement'

(same for differential_on_measurement, but it is only present in the README so I don't if it's relevant)

Am I doing something wrong or is there a problem in the class ?

output the control errors

It would be nice to have an option to output the control errors output along with the control, so they can be saved for analysis:

For example:
pid.show_errors = True
output, p_err, i_err, d_err = pid(current_value)

I could get them from the command p, i, d = pid.components, but not as cleanly.

Nice package, thanks!

Allow to specify last_output at PID creation

The first output from the PID will always be zero, I don't know if this is by design or a just how the math turned out but it is a bit annoying to turn on the PID, system is at the setpoint yet the pid throws in a zero

I found a way around it by doing:

pid.set_auto_mode(False)
pid.set_auto_mode(True, last_output=last_output_guess)

it's a hacky way of getting what I want but since I can read the current settings from my equipment and from there calculate what the last output from the pid would have been, I don't want the pid to output a 0 and send the system into a frenzy for no reason.

All this to say, I propose allowing optional keyword last_output in the PID.__init__ method.

edit:
I've gotten the behavior I wanted by including optional keyword last_output and adding the following lines to the end of the init method:

if not last_output is None: 
    self._integral = _clamp(last_output, self.output_limits).

Rename PID module

As mentioned in #48, calling the module PID.py is not very appropriate. To follow pep 8 it should be called pid.py instead. Think about how breaking this change would be and possibly rename the module.

output_limits incompatible with calling pid on non-singleton arrays

Hey there,

I'd like to call pid on a (2,) numpy array (say), as in:


pid = PID(1,2,3,setpoint=0)
cv = pid(pv)

This works fine UNLESS I set

pid.output_limits = (-10, 10)

which itself works fine when pid is called on singletons. Otherwise I get the error:

Traceback (most recent call last):
  File "C:\Users\james\anaconda3\envs\venv37_drift_null\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "C:\Users\james\anaconda3\envs\venv37_drift_null\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "<input>", line 92, in driftNulling
  File "C:\Users\james\anaconda3\envs\venv37_drift_null\lib\site-packages\simple_pid\PID.py", line 101, in __call__
    self._integral = _clamp(self._integral, self.output_limits)  # avoid integral windup
  File "C:\Users\james\anaconda3\envs\venv37_drift_null\lib\site-packages\simple_pid\PID.py", line 9, in _clamp
    elif upper is not None and value > upper:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Any hints ?

Thanks !

Gustavo

restarting the PID from an interrupt

Am I understanding correctly that if I needed to interrupt the PID and wanted to resume it from where it left off, I would need to save the:

        self._proportional = 0
        self._integral = 0
        self._derivative = 0

values and then set them when starting it back up again? Would I also need to do something with:

        self._last_time = _current_time()
        self._last_output = None
        self._last_input = None

It might be nice to have save() and load() methods to automate this.

non-monotonic time issue

Hi martin,

i'm using a similar PID implementation on a raspberry pi in a production environement (PID code is also based Brett Beauregard's code at ).

Turns out that both time.time() and datetime.datetime.now() are non-monotonic time signals. I.e. if a system service or the user turns the time back, the PID will see negative time differences. This happens on many systems (in particular the raspberry pi) regularly which has given me rare, but quite erratic behavior of the machine.

Fixed the problem using time.monotonic() which is available since python 3.3. Maybe this is helpful to your code too.

Best,
Deniz

MicroPython Port.

Hello!

Do you have plans to support the MicroPython?

I think that on the pid.py needs just to change the import warnings to an equivalent in MicroPython, right?

And about the performance, maybe needs change something more to better fit on the MicroPython?

Thank you.

Improve tests

The test suite for this library could be improved. The biggest problem is that it's not completely deterministic, so sometimes tests can fail due to timing and pass if you just rerun it. It should be fixed so that you get the same result every time running a test. Possibly dt and/or time_fn() could help. Some care needs to be taken so that the tests still test what they intend to test though.

The tests also take a needlessly long time to run, mostly because of test_converge_system(). It would be nice if this could be sped up.

I'm sure one could think of more tests to add too.

Tracking and output of PID terms to PV

I would like to track to individual contributions of the PID terms to the PV output in order to facilitate manual tuning of hard to tune loops. Can this be facilitated in the current implementation?

Integral windup problem

Hi
firstly, I would like to thank you for your nice library. It is very helpful and straightforward to use.
I think there is a problem in integral wind-up implementation. your code is correct, However the C code reference you have used, has a mistake in my opinion. Here in the solution- step1 has explained what should be done if output exceeds the limits. STOP INTEGRATING. How ever, in the code it stops integration only if the integral term exceeds the output limit which means integration won't stop even if the output is out of range. I have checked this and the result is here. The green curve shows the PID output which has been clamped and the cyan show the integral term (using pid.components).
Please correct me if I am wrong.
Regards

adding a filter to derivative term

👋 what are your thoughts on allowing users to add a hook into the class to add a filter infront of the derivative term. I've read in a few places that adding a filter infront of the derivative term is a good idea (i.e. instead of passing the raw input_ to d_input, we pass in some filtered version).

High level:

def my_filter(input_, previous_input_):
   # compute things    
   return some_float

pid = PID(...)
pid.add_derivative_hook(my_filter)

low level:

   
   def _compute_derivative(self, input, last_input):
       return input - (last_input if (last_input is not None) else input)

   def add_derivative_hook(self, callable):
       self._compute_derivative = callable

   def __call__(...):
        ...
        # Compute error terms
        error = self.setpoint - input_
        d_input = self._compute_derivative(input, self._last_input)
       ...

Question: how to incorporate a slew rate?

For reference - this package works pretty nicely as it stands. I'm wondering how one might add a slew rate, in order to set the maximum "acceleration" of the PID. Perhaps with error_map ? (Is this where the slew term goes in?)

No module named simple_pid

I downloaded the files as pip3 install simple-pid and it downloaded in the /home/pi/.local/lib/python3.7.

However, every time I try to run my program it says No module named simple_pid. How do I resolve this issue?

Add more examples

There is currently only one quite basic example to show how the PID controller should be used. It would be nice to have some more examples, perhaps also showing the more advanced/specialized features provided by the library (set_auto_mode(), error_map, the various possible values of output_limits etc). The examples should still be as short and to the point as possible while being complete and runnable.

what is the controlled system?

what is the controlled system? can i change the controlled system by change some params, like set the process transfer functionin as 1/(s^2+1) in matlab?

DC Servo Motor position control with an implemented Fuzzy-PID Controller using Raspberry Pi Pico

Hello! May I ask if you have any ideas on how to program/code a Fuzzy-PID Controller in Raspberry Pi Pico/Micropython?
I have a project on implementing a control system, Fuzzy-PID Controller, in my DC Servo Motor for the position control using RPi Pico. Well, my college department does not authorize the use of Arduino. :((
I saw your repositories and see it as a guide, tho, I'm still confused because mine is position control.
The model of my servo motor is DSS-M15S.

PID setpoint not in PID.pyi

The public attribute setpoint in simple_pid.PID.PID is not exposed in the .pyi.

When scanning with mypy, it throws an error:

error: "PID" has no attribute "setpoint"  [attr-defined]

A few ideas:

  • Add setpoint to the .pyi
  • Make setpoint private if it's not supposed to be public

Versions

Python==3.8.5
simple-pid==1.0.0
mypy==0.812

Setting last output, even when auto mode is on.

Hello,

I was working with setting the last_output value by calling pid.set_auto_mode(True, last_output=X). The issue I was having is that the auto mode was already on, so the last_output value was not being updated.

This looks to be the intended functionality as the code for set_auto_mode checks if auto_mode is currently on. What I'm wondering is if we could update the docs to state that if you want to set the last_output value, you must first turn auto_mode off, or if we could add a function solely for setting the last_output value.

It's also possible that setting the last output value during an auto mode is not advisable.

Thanks!

Duplicate state after updating measurement

Hi,
I am doing some testing and noticed that the internal state did not change after I updated the measurement value, is this normal?

00:02:00:03 517.3335 0.5173335 (0.5173335, 5.173335e-19, 0.0)
00:03:00:01 510.3335 0.8164169 (0.5103335, 0.3062001, -0.0001166667)
00:04:00:02 669.6335 1.380269 (0.6696335, 0.7079802, 0.002655)
00:05:00:05 826.2334 2.040783 (0.8262335, 1.211982, 0.002567212)
00:06:00:04 960.8334 2.040783 (0.8262335, 1.211982, 0.002567212) <------------
00:07:00:04 1104.033 3.63215 (1.104033, 2.525782, 0.002334454)
00:08:00:04 1216.533 4.474111 (1.216534, 3.255702, 0.001875)
00:09:00:01 1347.133 5.413293 (1.347134, 4.063982, 0.002176666)
00:10:00:03 1482.533 6.438293 (1.482534, 4.953503, 0.002256667)
00:11:00:02 1593.534 7.505007 (1.593534, 5.909623, 0.001850008)
00:12:00:04 1721.934 8.684042 (1.721934, 6.960003, 0.002104918)
00:13:00:01 1828.434 8.684042 (1.721934, 6.960003, 0.002104918) <-------------

In this data the 1st column is effectively time (HH:MM:SS:FF) and you will notice that I am slowly updating every 60s or so. I have limitations in my system which means I need to slow the PID down for now as I can't adjust the control too quickly... I have plans to improve this soon. 2nd data is the measurement (time delta in us), 3rd is out (adjustment to PIO clock divider)

My control loop is slowed by the speed which I can write data to the OLED screen on my Pico. It is only grabbing a measurement around 3Hz, and also averaging that to remove jitter noise from servicing the interrupts which are used to create timestamp.

Higher order discretizations [Enhancement]

Dear @m-lundberg,

I am currently working on PID control and wondered whether you considered higher order discretizations like a backward Euler or the Tustin/Trapezoidal method. I am not entirely certain how much we might benefit from such an adaptation, but I think your framework is really powerful and neat. Embedding a higher order controller in it would allow an easy comparison of different discretizations.

For an overview of the above mentioned methods consider this webpage.

Please respond if you are interested / still accepting contributions.

Best,

Gianni

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.