russtedrake / manipulation Goto Github PK
View Code? Open in Web Editor NEWCourse notes for MIT manipulation class
License: BSD 3-Clause "New" or "Revised" License
Course notes for MIT manipulation class
License: BSD 3-Clause "New" or "Revised" License
when the environment has tunneling enabled, I would like to be able to print out the link that users should point their browsers to from inside my code. how can I reconstruct the proper URL?
I would also need a way to reliably test if the code is running on deepnote or not. Presumably this would be resolved by whatever method I use to get the URL.
also:
The stochastic approximation has
x <- x - eta * [ l(x + w) - l(x) ] w
but the true gradient should be
x <- x - eta * [ l(x + w) - l(x) ] w / sigma^2
so we seem to be off at a scale.
This exercise is also bit misleading since it gives you the impression that we got out of local minima because we did zeroth-order, when in fact, we could have achieved the same effect by doing first order while injecting stochasticity.
I'd love to reimplement this problem with what we've learned with various gradient estimators over the past year.
The implementation of GenerateHtml has been temporarily removed from Drake due to licensing restrictions.
It just shows the above message, while running on own machine.
The following line in exercises/pick/differential_ik_optimization.ipynb
(exercise 3.9) fails:
simulator = BuildAndSimulate(DiffIKQP, V_d)
<ipython-input-10-48b45d3b8fa8> in DiffIKQP(J_G, V_G_desired, q_now, v_now, p_now)
9 prog.AddCost(error.dot(error))
10 solver = SnoptSolver()
---> 11 result = solver.Solve(prog)
12
13 if not (result.is_success()):
ValueError: The drake::solvers::SnoptSolver is not available in this build
(as we have in the cmake logic)
Involves finishing #4 and the TODOs in WORKSPACE:
# TODO(russt): set MPLBACKEND=Template environment variable for tests"
# TODO(russt): add python lint tests
# TODO(russt): tests fail on drake deprecated warning
then flipping CI to use the bazel tests instead of cmake. then zap the cmake.
some tests are failing right now -- fine to disable them to get this done.
so that it doesn't need to get installed on the first call to StartMeshcat.
Now that Drake has removed it: RobotLocomotion/drake#14691 .
It's currently coming from the policy gradient exercise:
==================== Test output for //exercises/rl:policy_gradient:
Matplotlib created a temporary config/cache directory at /var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/matplotlib-cukhora2 because the default path (/Users/runner/.matplotlib) is not a writable directory; it is highly recommended to set the MPLCONFIGDIR environment variable to a writable directory, in particular to speed up the import of Matplotlib and to better support multiprocessing.
Traceback (most recent call last):
File "/private/var/tmp/_bazel_runner/7b4dc6001ecdbeb1b5ef1e14edba8c[37](https://github.com/RussTedrake/manipulation/runs/7597131080?check_suite_focus=true#step:5:38)/sandbox/darwin-sandbox/47/execroot/manipulation/bazel-out/darwin-fastbuild/bin/exercises/rl/policy_gradient.runfiles/manipulation/exercises/rl/policy_gradient.ipynb.py", line 23, in <module>
from scipy.signal import lfilter
ModuleNotFoundError: No module named 'scipy'
================================================================================
and pymcubes
==================== Test output for //:trajectories:
Matplotlib created a temporary config/cache directory at /var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/matplotlib-6aqucvrt because the default path (/Users/runner/.matplotlib) is not a writable directory; it is highly recommended to set the MPLCONFIGDIR environment variable to a writable directory, in particular to speed up the import of Matplotlib and to better support multiprocessing.
Traceback (most recent call last):
File "/private/var/tmp/_bazel_runner/7b4dc6001ecdbeb1b5ef1e14edba8c37/sandbox/darwin-sandbox/355/execroot/manipulation/bazel-out/darwin-fastbuild/bin/trajectories.runfiles/manipulation/trajectories.ipynb.py", line 24, in <module>
import mcubes
File "/private/var/tmp/_bazel_runner/7b4dc6001ecdbeb1b5ef1e14edba8c37/sandbox/darwin-sandbox/3[55](https://github.com/RussTedrake/manipulation/runs/7597131080?check_suite_focus=true#step:5:56)/execroot/manipulation/bazel-out/darwin-fastbuild/bin/trajectories.runfiles/pip/pypi__pymcubes/mcubes/__init__.py", line 4, in <module>
from .smoothing import *
File "/private/var/tmp/_bazel_runner/7b4dc6001ecdbeb1b5ef1e14edba8c37/sandbox/darwin-sandbox/355/execroot/manipulation/bazel-out/darwin-fastbuild/bin/trajectories.runfiles/pip/pypi__pymcubes/mcubes/smoothing.py", line 11, in <module>
from scipy import sparse
ModuleNotFoundError: No module named 'scipy'
================================================================================
And adding it to requirements.in is breaking pip-compile. jazzband/pip-tools#1660
See render_html.js for an example
The new exercise downloads mustard pointclouds via urlretrieve
, but this breaks Mac CI.
Some notes:
running_as_notebook
this time because the whole exercise depends on the file.I will keep searching for a better solution.
Ubuntu 18.04
Drake version: 0.37.0, 0.39.0, 1.0.0
locationexercises/force/hybrid_force_position.ipynb
I have completed exercise 7.3 Hybrid Force-Position Control in deepnote with setted up environment. The robot pushes the book successfully to goal location. Later I decide to modify this exercise to do something else. To make developement easier, I try to use local environment. I set up the environemnt follow the guidance in https://manipulation.csail.mit.edu/drake.html#section2. However, I encounter a strange problem when try to run my completed exercise 7.3 locally. The iiwa robot only closes its gripper, but it will not move. The version of drake that I used is 0.37.0
. Later I have try different version of Drake like 0.39.0
and 1.0.0
. However, the problem persists and the iiwa robot does not move. To make sure that my drake is installed corretly, I run some other examples, like intro.ipynb
and manipulation_station.ipynb
. Everything seems to be fine.
I have also tried to run this exercise in my friend's computer with his setted up drake environemnt and I got same behavior: the iiwa robot does not move, only the gripper is closed. This bug seems to be repeatable.
From #79, Open3d is reverted to v0.10.0 due to:
isl-org/Open3D#2509
isl-org/Open3D#2508
Will need to update to v0.11.0 in the future as these issues are resolved.
Posted as a suggestion here:
https://community.deepnote.com/c/suggestions/output-cells-for-anyone-with-the-link-can-execute-this-project?
I'm also quite happy to hear that this is not a good idea!
| OS: Ubuntu 20.04 | Python: 3.8 | Drake 1.2.0 Stable Release | using venv through PyCharm |
Issue: DeepNote Chapter 2 Tutorial/Example problem is unable to find necessary packages when using Drake 1.2.0
Notes to help clear up the issue:
(1) The DeepNote (and Textbook) does not indicate what stable release of Drake it was built to work with.
(2) The most recent (1.2.0) release of Drake does not support Python 3.7 or 3.6
(3) The most current (v2021.0) release of this manipulation package requires Python <3.8
(in addition) Some utilities appear to have changed locations or names after the last update to the tutorials
In problem 9.1.d of stochastic_optimization.ipynb
:
def approximated_gradient_with_baseline(x, rate, baseline):
"""
Update rule. Receive theta and update it with the next theta.
@params
- x: input variable x.
- rate: rate of descent, variable "eta".
- baseline: float for baseline.
@returns:
- updated varaible x.
"""
return x
varaible -> variable
Looking forward to the semester!
I was taking manipulation course self-paced and today I saw the error, which never appeared before:
Tunnel 2306fa0eaf41.ngrok.io not found
I reproduce this issue in several notebooks and over few different internet options, available to me.
Was the visualization server taken down?
...github may be considered not the best place to raise this issue, so I apologize for that.
The link to drake.mit.edu is broken in this section. It tries to go to https://github.com/RussTedrake/manipulation/blob/master/exercises/robot/drake.mit.edu instead of https://drake.mit.edu
Related to #144 . This is a possible work-around for lack of interaction in deepnote (and spotty support for ipywidgets more generally in the jupyter-like cloud notebook ecosystem).
set_control
, e.g. via this.set_control("test", this.mycallback, 50, 0, 100, 0.1);
in the javascript to add a slider to the ui.set_control
messages are also parsed in the javascript, it's easy enough to pass them through the zmqserver.this.set_control("test", '(value) => this.connection.send("slider=" + value)', 50, 0, 100, 0.1);
update_control
for this? Or a variant of set_control
that takes only the value.update_control
messages.Note that the python client receiving the ui updates need not be the original meschat.Visualizer()
object. I'd be happy to have a separate meshcat.UISubscriber()
type object instead. It might be cleaner.
Running bazel on a clean ubuntu install with my (upcoming) hermitic-only pip caused one failure:
ERROR: /home/russt/manipulation/figures/BUILD.bazel:10:14: Executing genrule //figures:grasp_frames_nbconvert failed (Exit 1): bash failed: error executing command /bin/bash -c ... (remaining 1 argument(s) skipped)
Use --sandbox_debug to see verbose messages from the sandbox bash failed: error executing command /bin/bash -c ... (remaining 1 argument(s) skipped)
Use --sandbox_debug to see verbose messages from the sandbox
Traceback (most recent call last):
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/pip/pypi__traitlets/traitlets/traitlets.py", line 528, in get
value = obj._trait_values[self.name]
KeyError: 'template_paths'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/manipulation/htmlbook/tools/jupyter/nbconvert_script.py", line 31, in <module>
main(sys.argv[1])
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/manipulation/htmlbook/tools/jupyter/nbconvert_script.py", line 19, in main
exporter = PythonExporter()
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/pip/pypi__nbconvert/nbconvert/exporters/templateexporter.py", line 325, in __init__
super().__init__(config=config, **kw)
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/pip/pypi__nbconvert/nbconvert/exporters/exporter.py", line 114, in __init__
self._init_preprocessors()
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/pip/pypi__nbconvert/nbconvert/exporters/templateexporter.py", line 491, in _init_preprocessors
conf = self._get_conf()
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/pip/pypi__nbconvert/nbconvert/exporters/templateexporter.py", line 507, in _get_conf
for path in map(Path, self.template_paths):
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/pip/pypi__traitlets/traitlets/traitlets.py", line 556, in __get__
return self.get(obj, cls)
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/pip/pypi__traitlets/traitlets/traitlets.py", line 535, in get
value = self._validate(obj, dynamic_default())
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/pip/pypi__nbconvert/nbconvert/exporters/templateexporter.py", line 518, in _template_paths
template_names = self.get_template_names()
File "/home/russt/.cache/bazel/_bazel_russt/7bcbcd19e064ca0197e4cfaf8f9df35e/sandbox/linux-sandbox/1279/execroot/manipulation/bazel-out/k8-fastbuild/bin/htmlbook/tools/jupyter/nbconvert.runfiles/pip/pypi__nbconvert/nbconvert/exporters/templateexporter.py", line 601, in get_template_names
raise ValueError('No template sub-directory with name %r found in the following paths:\n\t%s' % (base_template, paths))
ValueError: No template sub-directory with name 'python' found in the following paths:
/home/russt/.local/share/jupyter
/usr/local/share/jupyter
/usr/share/jupyter
For now, I've just pegged the nbconvert revision on ubuntu.
@jamiesnape kindly offered to update this repo as done in RussTedrake/underactuated#234
that's' annoying for testing and probably not great in general.
A couple of minor typos in exercises/pose/ransac.ipynb (Exercise 4.6):
Now all you need to do is to remove the points that belong to the planar surface. You may do so by rejecting all points that are
\begin{equation}
|| a x + b y + c z + d || > tol
\end{equation}
plane_equation
parameter doesn't exist in the following function, and the main docstring isn't relevant:def remove_plane(point_cloud, ransac, tol=1e-4):
"""
Find the nearest (Euclidean) neighbor in point_cloud_B for each
point in point_cloud_A.
Args:
point_cloud: Nx3 numpy array of points
ransac: The RANSAC function to use (call ransac(args))
plane_equation: (4,) numpy array, contains the coefficients of the plane
Returns:
point_cloud_wo_plane: Nx3 numpy array of points
"""
I've confirmed that pip install manipulation (from pypl) does contain the model files. But it seems somehow that the wheel built from the pip direct from git workflow does not.
I suspect it is not using my MANIFEST.in file. But haven't been able to root cause the difference yet.
and remove the (unnecessary) dependencies of scipy and scikit-learn
will wait til pset 2 is fully submitted.
cc @hjsuh94
@sammy-tri -- have you managed to discuss this yet? anything I can do to help?
teleop_2d_direct(interactive=True) will cause EOF error for autograder due to calling input()
.
A solution would be using slide bar (maybe ipywidgets) instead of input() for interactive mode.
See this piazza post
I've pinned the revision to 4.2.2 due to the breaking change, reported in the changelog:
ngrok.connect() now returns a NgrokTunnel instead of a str of the public URL. The returned NgrokTunnel has a reference to the previously returned public_url in it.
will need to update meshcat-python
On Firefox 105.0 (Ubuntu 20.04), as of fbc1580:
https://manipulation.csail.mit.edu/pick.html#diff_ik_w_constraints
At normal zoom:
At 110% zoom, then it appears:
If I copy a file from drake that passes drake's linter (which forced me to put docstrings on a new line), then I get
manipulation/jupyter_widgets.py:1 at module level:
D212: Multi-line docstring summary should start at the first line
manipulation/jupyter_widgets.py:38 in public method `__init__`:
D212: Multi-line docstring summary should start at the first line
manipulation/jupyter_widgets.py:102 in public method `set_positions`:
D212: Multi-line docstring summary should start at the first line
manipulation/jupyter_widgets.py:119 in public method `set_joint_positions`:
D212: Multi-line docstring summary should start at the first line
manipulation/jupyter_widgets.py:152 in public function `MakeJointSlidersThatPublishOnCallback`:
D212: Multi-line docstring summary should start at the first line
@jamiesnape -- can we configure yapf here to either ignore that warning or make it compatible?
When a user duplicates a project from my "share project" link, the Environment should get duplicated, too. In particular, I need to duplicate:
I need to point them to the updated binaries, or convert them to installing underactuated.
i believe it now requires an account; need to request an edu account from dockerhub. Update: submitted request form on 2021/08/30
Reported here and by a few collaborators.
It seems that some time after Aug 10 and before Aug 18, ngrok
changed its policy and no longer allows http tunnels to connect ws tunnels on the free account. I have not verified myself, but I understand that logging in to a user account on ngrok resolves the issue. (there is still a limit of 2 connections; passing bind_tls=False
to pyngrok
helps; otherwise pyngrok grabs http and https for the first request, consuming the full quota immediately).
This is bad news. Effectively all of the notebooks that I've released to date will no longer run meshcat on colab.
Possible resolutions:
In particular, it would be nice to have more real-estate when using the teleop sliders.
Here is a javascript snippet that does the trick, but it's not pretty. I could plumb it through the websockets if we like.
var viewer = new MeshCat.Viewer(document.getElementById("meshcat-pane"));
viewer.set_control("TestSlider", (value) => {
console.log("TestSlider = " + value);
}, .5, 0, 1, 0.01);
viewer.set_control("ExtendSliders", (value) => {
let e = viewer.gui_controllers.TestSlider.domElement;
e.parentElement.parentElement.style.marginLeft="-300px";
e.parentElement.querySelector(".property-name").style.width="15%";
e.style.width="85%";
e.querySelector(".slider").style.width="89%";
e.querySelector("input").style.width="10%";
}, .5, 0, 1, 0.01);
viewer.set_control_value("ExtendSliders", .01); // To execute the callback.
viewer.delete_control("ExtendSliders");
Making this issue to track my progress
at least on the pip CI.
I'm not sure if this is an actual issue or I'm doing something wrong but I noticed that the gripper positions and rpy values printed out are not consistent for the same values of iiwa joint angles.
Steps to reproduce:
Expected behavior: every time the iiwa joint angles are the same, the gripper position and rpy should show the same values.
Example output currently:
first set to 0
gripper position (m): [0.00 -0.47 0.68]
gripper roll-pitch-yaw (rad):[-1.81 -0.00 0.00]
set to 1
gripper position (m): [0.47 0.00 0.68]
gripper roll-pitch-yaw (rad):[-1.81 -0.00 1.57]
set to 0
gripper position (m): [0.25 0.39 0.68]
gripper roll-pitch-yaw (rad):[-1.81 -0.00 2.57]
set to -1
gripper position (m): [0.47 0.00 0.68]
gripper roll-pitch-yaw (rad):[-1.81 -0.00 1.57]
set to 0
gripper position (m): [0.25 -0.39 0.68]
gripper roll-pitch-yaw (rad):[-1.81 -0.00 0.57]
set to 1
gripper position (m): [0.47 0.00 0.68]
gripper roll-pitch-yaw (rad):[-1.81 -0.00 1.57]
set to 0.1
gripper position (m): [0.47 0.00 0.68]
gripper roll-pitch-yaw (rad):[-1.81 -0.00 1.57]
set to 1.56
gripper position (m): [0.46 0.05 0.68]
gripper roll-pitch-yaw (rad):[-1.81 -0.00 1.67]
set to 0
gripper position (m): [0.01 0.47 0.68]
gripper roll-pitch-yaw (rad):[-1.81 -0.00 3.13]
I am installing the repo and drake nightly with
pip install -U https://drake-packages.csail.mit.edu/drake/nightly/drake-latest-cp310-cp310-manylinux_2_31_x86_64.whl
pip install git+https://github.com/RussTedrake/manipulation@master
Then if we do from manipulation import running_as_notebook
, an error would rise with ImportError: cannot import name 'RenderLabel' from 'pydrake.geometry'
I am wondering if we shall change this line to from pydrake.geometry.render import RenderLabel
I am having trouble understanding why the iiwa model is being loaded here again. Wasn't the iiwa robot being loaded via the the model directives in the function here?
What was the reason you have maintained two different plants for the main system and the controller when setting up the manipulation station? Couldn't we add all the elements to the same instance of the Multibody plant? Am I missing something here?
Thank you for your work and instruction, it has been very helpful.
RuntimeError Traceback (most recent call last)
Cell In [4], line 16
6 #file: package://manipulation/models/clutter.dmd.yaml
7 model_directives = """
8 directives:
9 - add_directives:
(...)
13 file: package://drake/examples/manipulation_station/models/061_foam_brick.sdf
14 """
15 station = builder.AddSystem(
---> 16 MakeManipulationStation(model_directives=model_directives))
17 plant = station.GetSubsystemByName("plant")
18 plant.SetDefaultFreeBodyPose(plant.GetBodyByName("base_link"), X_O['initial'])
File ~/drake/lib/python3.10/site-packages/manipulation/scenarios.py:529, in MakeManipulationStation(model_directives, filename, time_step, iiwa_prefix, wsg_prefix, camera_prefix, package_xmls)
527 if model_directives:
528 directives = LoadModelDirectivesFromString(model_directives)
--> 529 ProcessModelDirectives(directives, parser)
530 if filename:
531 parser.AddAllModelsFromFile(filename)
RuntimeError: error: URI 'package://manipulation/models/clutter.dmd.yaml' refers to unknown package 'manipulation'
(and re-enable the disabled tests)
obviously, the desired behavior is that bazel run
shows the gui, but bazel test
does not.
For an example failure (with, unfortunately, no useful console output), see:
https://github.com/RussTedrake/manipulation/runs/1338886525?check_suite_focus=true
@mfeng9 -- this was your exercise.
I would love to get the drake provisioning started immediately upon a user opening the notebook, instead of waiting for them to run some cells. I've play around with it a bit in this notebook. I don't think it's currently possible on colab (and it's clear the community strongly discourages it as a security hazard). The irony is that I can automatically run arbitrary javascript code.
Based on initial testing, I don’t think I have enough access to ask the kernel to execute cells, or even examine cells, from javascript, unless I register at least one function that can be invoked, but that requires running a cell of python. I think at best I can have the user only have to run a single python cell. Not sure if doing more than that is worth the complexity that would result?
Here is the autorun.js version that works in normal jupyter.
https://gist.github.com/hainm/59b3b8da9ef96567edff656e2d6835e8
Note that, if I could get this to work, then I could actually put the drake provisioning, etc, in an appendix (like in ObservableHQ).
We don't use much of the functionality, so I only need to add a few more methods to Drake:
The first cell in the notebook lectures/qp_diff_ik.ipynb fails with:
ModuleNotFoundError: No module named 'manipulation.scenarios'
The issue is that the manipulation_sha
passed to setup_manipulation
was from before manipulation.scenarios
existed. Changing the sha to 3081d6b gets the notebook working.
The version of stochastic_optimization.ipynb
available in course colabs has stopped installing for me, failing with the error:
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-7-a9ee8c645c2f> in <module>()
8 # "setup_manipulation_colab.py")
9 from setup_manipulation_colab import setup_manipulation
---> 10 setup_manipulation(manipulation_sha='14145ea656da5bdeb7a7ae4fbd7e28b8e464e544', drake_version='0.25.0', drake_build='releases')
11
12 from IPython import get_ipython
2 frames
/content/setup_drake_colab.py in setup_drake(version, build)
110 # Confirm that we now have pydrake on the path.
111 assert spec is not None, (
--> 112 "Installation failed. find_spec('pydrake') returned None.")
113 assert path in spec.origin, (
114 "Installation failed. find_spec is locating pydrake, but not in the "
AssertionError: Installation failed. find_spec('pydrake') returned None.
Could this be resolved?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.