zmk5 / jupyter-ros2 Goto Github PK
View Code? Open in Web Editor NEWThis project forked from robostack/jupyter-ros
Jupyter widget helpers for ros2, the Next-Generation of the Robot Operating System
This project forked from robostack/jupyter-ros
Jupyter widget helpers for ros2, the Next-Generation of the Robot Operating System
The command
$ jupyter labextension install jupyter-ros2
gives an error
An error occured.
ValueError: "/home/user/notebook/jupyter-ros2" is not a valid npm package
See the log file for details: /tmp/jupyterlab-debug-c411be55.log
So I tried the development installation
~$ git clone https://github.com/zmk5/jupyter-ros2.git
~$ cd jupyter-ros2
~$ python3 -m pip install -e .
The error log is
ERROR: Command errored out with exit status 1:
command: /usr/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/home/user/notebook/jupyter-ros2/setup.py'"'"'; __file__='"'"'/home/user/notebook/jupyter-ros2/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info
cwd: /home/user/notebook/jupyter-ros2/
Complete output (155 lines):
setup.py entered
$PATH=/opt/ros/foxy/bin:/home/hsd/projects/rosin/env3/bin:/home/user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
running egg_info
running jsdeps
7.11.2
7.11.2
Installing build dependencies with npm. This may take a while...
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: '[email protected]',
npm WARN EBADENGINE required: { node: '>= 10.23.1 <13.0.0' },
npm WARN EBADENGINE current: { node: 'v16.1.0', npm: '7.11.2' }
npm WARN EBADENGINE }
npm ERR! code 1
npm ERR! git dep preparation failed
npm ERR! command /usr/bin/node /usr/lib/node_modules/npm/bin/npm-cli.js install --force --cache=/home/user/.npm --prefer-offline=false --prefer-online=false --offline=false --no-progress --no-save --no-audit
npm ERR! > [email protected] install
npm ERR! > node-gyp rebuild
npm ERR!
npm ERR! make: Entering directory '/home/user/.npm/_cacache/tmp/git-clone-c1189b66/build'
npm ERR! CXX(target) Release/obj.target/rclnodejs/src/addon.o
npm ERR! CXX(target) Release/obj.target/rclnodejs/src/executor.o
npm ERR! CXX(target) Release/obj.target/rclnodejs/src/handle_manager.o
npm ERR! CXX(target) Release/obj.target/rclnodejs/src/rcl_action_bindings.o
npm ERR! CXX(target) Release/obj.target/rclnodejs/src/rcl_bindings.o
npm ERR! CXX(target) Release/obj.target/rclnodejs/src/rcl_handle.o
npm ERR! CXX(target) Release/obj.target/rclnodejs/src/rcl_lifecycle_bindings.o
npm ERR! make: Leaving directory '/home/user/.npm/_cacache/tmp/git-clone-c1189b66/build'
npm ERR! npm WARN using --force Recommended protections disabled.
npm ERR! npm WARN deprecated [email protected]: this library is no longer supported
npm ERR! npm WARN deprecated [email protected]: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.
npm ERR! npm WARN deprecated [email protected]: request has been deprecated, see https://github.com/request/request/issues/3142
npm ERR! gyp info it worked if it ends with ok
npm ERR! gyp info using [email protected]
npm ERR! gyp info using [email protected] | linux | x64
npm ERR! gyp info find Python using Python version 3.8.5 found at "/usr/bin/python3"
npm ERR! (node:87378) [DEP0150] DeprecationWarning: Setting process.config is deprecated. In the future the property will be read-only.
npm ERR! (Use `node --trace-deprecation ...` to show where the warning was created)
npm ERR! gyp info spawn /usr/bin/python3
npm ERR! gyp info spawn args [
npm ERR! gyp info spawn args '/usr/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
npm ERR! gyp info spawn args 'binding.gyp',
npm ERR! gyp info spawn args '-f',
npm ERR! gyp info spawn args 'make',
npm ERR! gyp info spawn args '-I',
npm ERR! gyp info spawn args '/home/user/.npm/_cacache/tmp/git-clone-c1189b66/build/config.gypi',
npm ERR! gyp info spawn args '-I',
npm ERR! gyp info spawn args '/usr/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
npm ERR! gyp info spawn args '-I',
npm ERR! gyp info spawn args '/home/user/.cache/node-gyp/16.1.0/include/node/common.gypi',
npm ERR! gyp info spawn args '-Dlibrary=shared_library',
npm ERR! gyp info spawn args '-Dvisibility=default',
npm ERR! gyp info spawn args '-Dnode_root_dir=/home/user/.cache/node-gyp/16.1.0',
npm ERR! gyp info spawn args '-Dnode_gyp_dir=/usr/lib/node_modules/npm/node_modules/node-gyp',
npm ERR! gyp info spawn args '-Dnode_lib_file=/home/user/.cache/node-gyp/16.1.0/<(target_arch)/node.lib',
npm ERR! gyp info spawn args '-Dmodule_root_dir=/home/user/.npm/_cacache/tmp/git-clone-c1189b66',
npm ERR! gyp info spawn args '-Dnode_engine=v8',
npm ERR! gyp info spawn args '--depth=.',
npm ERR! gyp info spawn args '--no-parallel',
npm ERR! gyp info spawn args '--generator-output',
npm ERR! gyp info spawn args 'build',
npm ERR! gyp info spawn args '-Goutput_dir=.'
npm ERR! gyp info spawn args ]
npm ERR! gyp info spawn make
npm ERR! gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
npm ERR! ../src/rcl_bindings.cpp: In function ‘Nan::NAN_METHOD_RETURN_TYPE rclnodejs::CreateArrayBufferFromAddress(Nan::NAN_METHOD_ARGS_TYPE)’:
npm ERR! ../src/rcl_bindings.cpp:1322:70: warning: ‘static v8::Local<v8::ArrayBuffer> v8::ArrayBuffer::New(v8::Isolate*, void*, size_t, v8::ArrayBufferCreationMode)’ is deprecated: Use the version that takes a BackingStore. See http://crbug.com/v8/9908. [-Wdeprecated-declarations]
npm ERR! 1322 | v8::ArrayBufferCreationMode::kInternalized);
npm ERR! | ^
npm ERR! In file included from /home/user/.cache/node-gyp/16.1.0/include/node/node.h:63,
npm ERR! from ../node_modules/nan/nan.h:56,
npm ERR! from ../src/rcl_bindings.hpp:18,
npm ERR! from ../src/rcl_bindings.cpp:15:
npm ERR! /home/user/.cache/node-gyp/16.1.0/include/node/v8.h:5476:29: note: declared here
npm ERR! 5476 | static Local<ArrayBuffer> New(
npm ERR! | ^~~
npm ERR! ../src/rcl_bindings.cpp:1322:70: warning: ‘static v8::Local<v8::ArrayBuffer> v8::ArrayBuffer::New(v8::Isolate*, void*, size_t, v8::ArrayBufferCreationMode)’ is deprecated: Use the version that takes a BackingStore. See http://crbug.com/v8/9908. [-Wdeprecated-declarations]
npm ERR! 1322 | v8::ArrayBufferCreationMode::kInternalized);
npm ERR! | ^
npm ERR! In file included from /home/user/.cache/node-gyp/16.1.0/include/node/node.h:63,
npm ERR! from ../node_modules/nan/nan.h:56,
npm ERR! from ../src/rcl_bindings.hpp:18,
npm ERR! from ../src/rcl_bindings.cpp:15:
npm ERR! /home/user/.cache/node-gyp/16.1.0/include/node/v8.h:5476:29: note: declared here
npm ERR! 5476 | static Local<ArrayBuffer> New(
npm ERR! | ^~~
npm ERR! ../src/rcl_lifecycle_bindings.cpp: In function ‘Nan::NAN_METHOD_RETURN_TYPE rclnodejs::CreateLifecycleStateMachine(Nan::NAN_METHOD_ARGS_TYPE)’:
npm ERR! ../src/rcl_lifecycle_bindings.cpp:76:3: error: ‘rcl_lifecycle_state_machine_options_t’ was not declared in this scope; did you mean ‘rcl_lifecycle_state_machine_init’?
npm ERR! 76 | rcl_lifecycle_state_machine_options_t options =
npm ERR! | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! | rcl_lifecycle_state_machine_init
npm ERR! In file included from ../src/rcl_lifecycle_bindings.cpp:29:
npm ERR! ../src/rcl_lifecycle_bindings.cpp:83:33: error: ‘options’ was not declared in this scope; did you mean ‘htons’?
npm ERR! 83 | &options),
npm ERR! | ^~~~~~~
npm ERR! ../src/macros.hpp:22:16: note: in definition of macro ‘CHECK_OP_AND_THROW_ERROR_IF_NOT_TRUE’
npm ERR! 22 | if (lhs op rhs) { \
npm ERR! | ^~~
npm ERR! ../src/rcl_lifecycle_bindings.cpp:79:3: note: in expansion of macro ‘THROW_ERROR_IF_NOT_EQUAL’
npm ERR! 79 | THROW_ERROR_IF_NOT_EQUAL(RCL_RET_OK,
npm ERR! | ^~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! ../src/rcl_lifecycle_bindings.cpp: In lambda function:
npm ERR! ../src/rcl_lifecycle_bindings.cpp:90:77: error: too few arguments to function ‘rcl_ret_t rcl_lifecycle_state_machine_fini(rcl_lifecycle_state_machine_t*, rcl_node_t*, const rcl_allocator_t*)’
npm ERR! 90 | rcl_ret_t ret = rcl_lifecycle_state_machine_fini(state_machine, node);
npm ERR! | ^
npm ERR! In file included from ../src/rcl_lifecycle_bindings.cpp:18:
npm ERR! /opt/ros/foxy/include/rcl_lifecycle/rcl_lifecycle.h:272:1: note: declared here
npm ERR! 272 | rcl_lifecycle_state_machine_fini(
npm ERR! | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm ERR! make: *** [rclnodejs.target.mk:138: Release/obj.target/rclnodejs/src/rcl_lifecycle_bindings.o] Error 1
npm ERR! gyp ERR! build error
npm ERR! gyp ERR! stack Error: `make` failed with exit code: 2
npm ERR! gyp ERR! stack at ChildProcess.onExit (/usr/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:194:23)
npm ERR! gyp ERR! stack at ChildProcess.emit (node:events:365:28)
npm ERR! gyp ERR! stack at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12)
npm ERR! gyp ERR! System Linux 5.8.0-53-generic
npm ERR! gyp ERR! command "/usr/bin/node" "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
npm ERR! gyp ERR! cwd /home/user/.npm/_cacache/tmp/git-clone-c1189b66
npm ERR! gyp ERR! node -v v16.1.0
npm ERR! gyp ERR! node-gyp -v v7.1.2
npm ERR! gyp ERR! not ok
npm ERR! npm ERR! code 1
npm ERR! npm ERR! path /home/user/.npm/_cacache/tmp/git-clone-c1189b66
npm ERR! npm ERR! command failed
npm ERR! npm ERR! command sh -c node-gyp rebuild
npm ERR!
npm ERR! npm ERR! A complete log of this run can be found in:
npm ERR! npm ERR! /home/user/.npm/_logs/2021-05-18T15_06_14_587Z-debug.log
npm ERR! A complete log of this run can be found in:
npm ERR! /home/user/.npm/_logs/2021-05-18T15_06_15_455Z-debug.log
rebuilding js and css failed
missing files: ['/home/user/notebook/jupyter-ros2/jupyros/static/extension.js', '/home/user/notebook/jupyter-ros2/jupyros/static/index.js']
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/user/notebook/jupyter-ros2/setup.py", line 182, in <module>
setup(**setup_args)
File "/home/user/.local/lib/python3.8/site-packages/setuptools/__init__.py", line 153, in setup
return distutils.core.setup(**attrs)
File "/usr/lib/python3.8/distutils/core.py", line 148, in setup
dist.run_commands()
File "/usr/lib/python3.8/distutils/dist.py", line 966, in run_commands
self.run_command(cmd)
File "/usr/lib/python3.8/distutils/dist.py", line 985, in run_command
cmd_obj.run()
File "/home/user/notebook/jupyter-ros2/setup.py", line 45, in run
raise e
File "/home/user/notebook/jupyter-ros2/setup.py", line 38, in run
self.distribution.run_command('jsdeps')
File "/usr/lib/python3.8/distutils/dist.py", line 985, in run_command
cmd_obj.run()
File "/home/user/notebook/jupyter-ros2/setup.py", line 111, in run
check_call(
File "/usr/lib/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['npm', 'install']' returned non-zero exit status 1.
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
As it not that easy to get all the dependencies in and get this to work, I thought of adapting the Dockerfile of the original repos author to ROS2 and this version here.
Think there are only some minor things missing but maybe the autor can help here.
For example in the 3D grid example it says Error displaying widget: model not found
when trying to view the ros3d.Viewer()
.
ipywidgets are installed, because calling a slider directly works but not when using jupyros.
Running the below Dockerfile leads to a running jupyterlab with ros2 support.
Dockerfile:
FROM ubuntu:bionic
RUN apt update && apt install -y git locales python curl wget
RUN locale-gen en_US en_US.UTF-8 && update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
ENV LANG en_US.UTF-8
RUN apt install -y gnupg2 lsb-release
RUN curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add -
RUN sh -c 'echo "deb [arch=amd64,arm64] http://packages.ros.org/ros2/ubuntu `lsb_release -cs` main" > /etc/apt/sources.list.d/ros2-latest.list'
# Install prerequisites
RUN export DEBIAN_FRONTEND=noninteractive && apt update && apt install -y \
build-essential \
cmake \
python3-colcon-common-extensions \
python3-pip \
python-rosdep \
libpython3-dev \
cppcheck
RUN rosdep init
RUN rosdep update
# Get ROS2 latest package
ENV ROS2_WS=/root
WORKDIR $ROS2_WS
RUN wget https://ci.ros2.org/view/packaging/job/packaging_linux/lastSuccessfulBuild/artifact/ws/ros2-package-linux-x86_64.tar.bz2 \
&& tar xf ros2-package-linux-x86_64.tar.bz2
# [Ubuntu 18.04]
RUN rosdep install --from-paths $ROS2_WS/ros2-linux/share --ignore-src --rosdistro dashing -y --skip-keys "console_bridge fastcdr fastrtps libopensplice67 libopensplice69 osrf_testing_tools_cpp poco_vendor rmw_connext_cpp rosidl_typesupport_connext_c rosidl_typesupport_connext_cpp rti-connext-dds-5.3.1 tinyxml_vendor tinyxml2_vendor urdfdom urdfdom_headers"
RUN echo "source $ROS2_WS/ros2-linux/local_setup.bash" >> $HOME/.bashrc
# Install nvm, Node.js and node-gyp
ENV NODE_VERSION v10.16.1
RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash \
&& . $HOME/.nvm/nvm.sh \
&& nvm install $NODE_VERSION && nvm alias default $NODE_VERSION
ENV PATH /bin/versions/node/$NODE_VERSION/bin:$PATH
RUN python3 -m pip install jupyter jupyterlab bqplot pyyaml ipywidgets opencv-python \
&& jupyter nbextension enable --py widgetsnbextension \
&& jupyter labextension install @jupyter-widgets/jupyterlab-manager
#&& jupyter nbextension enable --py --sys-prefix jupyros
#&& jupyter labextension install jupyter-ros
RUN rm ros2-package-linux-x86_64.tar.bz2
RUN git clone https://github.com/zmk5/jupyter-ros2.git
RUN curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
# need to copy to jupyros/static/ as pip asks for this path !? Don't know where it gets this path from...
RUN cd jupyter-ros2 \
&& mkdir -p jupyros/static && cp js/lib/* jupyros/static/ \
&& python3 -m pip install -e .
# RUN jupyter nbextension install --py --symlink --sys-prefix jupyros \
# && jupyter nbextension enable --py --sys-prefix jupyros
ENTRYPOINT ["jupyter", "lab", "--ip=0.0.0.0", "--no-browser", "--allow-root"]
Hi @zmk5
I wanted to ask if you think we can merge this project back into jupyter-ros? I think it would be great to bundle our efforts. And I am also happy to give you commit rights to the original repository.
Do you think it would be technically feasible?
Cheers!
Wolf
Ubuntu: 22.04
ROS2 Humble Hawksbill
Python 3.10
jupyros and dependencies installed correctly and I have provided sys path as my local ROS2 site-packages for humble as :
import sys
sys.path.append('/opt/ros/humble/lib/python3.10/site-packages/')
Then import jupyros
import jupyros
But this error kicks in as
`The rclpy package is not found in your $PYTHONPATH. Subscribe and publish are not going to work.
Do you need to activate your ros2 environment?
CvBridge not installed or sourced! Image messages will not work until then!
The rclpy package is not found in your $PYTHONPATH. Subscribe and publish are not going to work.
Do you need to activate your ros2 environment?
The rclpy package is not found in your $PYTHONPATH. Subscribe and publish are not going to work.
Do you need to activate your ros2 environment?
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [4], line 5
2 sys.path.append('/opt/ros/humble/lib/python3.10/site-packages/')
4 # The next line should now work!
----> 5 import jupyros
File ~/jupyter-ros2/jupyros/__init__.py:7
5 from .ipy import *
6 from .server_extension import *
----> 7 from .publisher import Publisher
8 from .subscription import Subscription
9 from .plot import LivePlot
File ~/jupyter-ros2/jupyros/publisher.py:25
21 # Used for documentation purposes only
22 MsgType = TypeVar('MsgType')
---> 25 class Publisher():
26 """
27 Creates a class containing the form widget for message type `msg_type`.
28 This class analyzes the fields of msg_type and creates
(...)
38
39 """
40 def __init__(self, node: Node, msg_type: MsgType, topic: str) -> None:
41 # Check if a ros2 node is provided.
File ~/jupyter-ros2/jupyros/publisher.py:40, in Publisher()
25 class Publisher():
26 """
27 Creates a class containing the form widget for message type `msg_type`.
28 This class analyzes the fields of msg_type and creates
(...)
38
39 """
---> 40 def __init__(self, node: Node, msg_type: MsgType, topic: str) -> None:
41 # Check if a ros2 node is provided.
42 if (not isinstance(node, Node) or not issubclass(type(node), Node)):
43 raise TypeError(
44 "Input argument 'node' is not of type rclpy.node.Node!")
NameError: name 'Node' is not defined
`
As my local ROS2 environment is clearly running. To make sure I even ran a ROS2 simple pub/subscript.
The command
jupyter nbextension install --user --py --symlink jupyros2
gives me an error
Traceback (most recent call last):
File "/home/user/.local/bin/jupyter-nbextension", line 8, in <module>
sys.exit(main())
File "/home/user/.local/lib/python3.8/site-packages/jupyter_core/application.py", line 254, in launch_instance
return super(JupyterApp, cls).launch_instance(argv=argv, **kwargs)
File "/usr/lib/python3/dist-packages/traitlets/config/application.py", line 664, in launch_instance
app.start()
File "/home/user/.local/lib/python3.8/site-packages/notebook/nbextensions.py", line 980, in start
super().start()
File "/home/user/.local/lib/python3.8/site-packages/jupyter_core/application.py", line 243, in start
self.subapp.start()
File "/home/user/.local/lib/python3.8/site-packages/notebook/nbextensions.py", line 708, in start
self.install_extensions()
File "/home/user/.local/lib/python3.8/site-packages/notebook/nbextensions.py", line 679, in install_extensions
full_dests = install(self.extra_args[0],
File "/home/user/.local/lib/python3.8/site-packages/notebook/nbextensions.py", line 203, in install_nbextension_python
m, nbexts = _get_nbextension_metadata(module)
File "/home/user/.local/lib/python3.8/site-packages/notebook/nbextensions.py", line 1114, in _get_nbextension_metadata
m = import_item(module)
File "/usr/lib/python3/dist-packages/traitlets/utils/importstring.py", line 42, in import_item
return __import__(parts[0])
ModuleNotFoundError: No module named 'jupyros2'
But changing that to
jupyter nbextension install --user --py --symlink jupyros
successfully installs the module
register_cell_magic not enabled!
Installing /home/user/notebook/jupyter-ros2/jupyros/static -> jupyter-ros
Symlinking: /home/user/.local/share/jupyter/nbextensions/jupyter-ros -> /home/user/notebook/jupyter-ros2/jupyros/static
- Validating: OK
To initialize this nbextension in the browser every time the notebook (or other app) loads:
jupyter nbextension enable jupyros --user --py
I am new to jupyter so I am not sure where to make the required changes
Compared to the original, ros2 requires the use of either a class rclpy.timer
or for the node to be used with rclpy.spin_once()
to even display the callback. A temporary solution requires a thread to keep spinning every tenth of a second to achieve a successful callback.
After installing jupyther the call to jupyter nbextension enable --py --sys-prefix ipywidgets
fails.
Both on my native Ubuntu 18.04 machine and in a docker container.
root@75289eaa9696:~# jupyter nbextension enable --py --sys-prefix ipywidgets
Traceback (most recent call last):
File "/usr/local/bin/jupyter-nbextension", line 11, in <module>
sys.exit(main())
File "/usr/local/lib/python3.6/dist-packages/jupyter_core/application.py", line 268, in launch_instance
return super(JupyterApp, cls).launch_instance(argv=argv, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/traitlets/config/application.py", line 664, in launch_instance
app.start()
File "/usr/local/lib/python3.6/dist-packages/notebook/nbextensions.py", line 983, in start
super(NBExtensionApp, self).start()
File "/usr/local/lib/python3.6/dist-packages/jupyter_core/application.py", line 257, in start
self.subapp.start()
File "/usr/local/lib/python3.6/dist-packages/notebook/nbextensions.py", line 891, in start
self.toggle_nbextension_python(self.extra_args[0])
File "/usr/local/lib/python3.6/dist-packages/notebook/nbextensions.py", line 867, in toggle_nbextension_python
logger=self.log)
File "/usr/local/lib/python3.6/dist-packages/notebook/nbextensions.py", line 478, in enable_nbextension_python
logger=logger)
File "/usr/local/lib/python3.6/dist-packages/notebook/nbextensions.py", line 375, in _set_nbextension_state_python
m, nbexts = _get_nbextension_metadata(module)
File "/usr/local/lib/python3.6/dist-packages/notebook/nbextensions.py", line 1120, in _get_nbextension_metadata
'it is missing the `_jupyter_nbextension_paths()` method.'.format(module))
KeyError: 'The Python module ipywidgets is not a valid nbextension, it is missing the `_jupyter_nbextension_paths()` method.'
npm -v
6.9.0
node -v
v10.16.1
The callback will only output to the of currently active cell instead of the respective cell where jp.publisher()
or jp.subscribe()
are located. This bug may require an widgets.Output
for each use of the former method calls.
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.