opencyphal / public_regulated_data_types Goto Github PK
View Code? Open in Web Editor NEWRegulated DSDL definitions for Cyphal (standard and third-party)
Home Page: https://nunaweb.opencyphal.org
License: MIT License
Regulated DSDL definitions for Cyphal (standard and third-party)
Home Page: https://nunaweb.opencyphal.org
License: MIT License
What is the meaning of hours_to_empty_at_10sec_avg_power_variance in 1. PrimaryPowerSupplyStatus(message type id:1090), and whether the calculation method is directly calculated by the variance formula?
CircuitStatus(message type id:1091):
2.1 What does circuit_id refer to?
2.2 Whether the voltage and current here are consistent with the voltage and current of 1092 does not represent what it means
BatteryInfo(message type id:1092)
3.1 temperature:Only one temperature? How to send if there are multiple temperatures?
3.2 battery_id:If one battery pack is 0, but there are multiple battery packs, how to allocate this ID? ? ?
3.3 Bit5 STATUS_FLAG_OVERLOAD : Does it mean that the power is too large, or the current is too large? ? ? ?
Are there any real examples of dynamic nodes, or the source code?
Ask for answers, thank you very much!!!
Some GNSS receivers output ECEF coordinates instead of LLA. Are there plans to provide support for these fields in a GNSS fix message?
https://github.com/UAVCAN/public_regulated_data_types/blob/master/reg/drone/service/battery/Parameters.0.1.uavcan has a parameter unique_id.
I think it needs more clarity on how it may be defined. If its 64 bits, is the idea for a vendor to use a random 40 most significant bits to identify the vendor and the rest bits to identify a particular battery ?
Also need clarity for uavcan.si.unit.electric_current.Scalar.1.0 charge_termination_treshold # End-of-charging current threshold
What does this parameter represent ?
Would be possible to host the generated headers of public_regulated_data_types on a Github repo?
This solves some quality of life issues for end-users
As mentioned at https://forum.uavcan.org/t/problems-with-ds-015/1219/32 the nested type should be a unit and not sample to remove the redundant timestamp.
pydsdl._dsdl_definition.FileNameFormatError: /home/weig/temp/backup_code/public_regulated_data_types/uavcan/CoarseOrientation.uavcan: Invalid file name
master branch is ok, please check, or make a latest release tag.
The log index should be widened from uint8 to match the maximum width of node-ID, which is 16 bit.
I do concur with @thirtytwobits about having a sample point option as well. Or at least thinking about minimal sample point or something like that. MCU's can indeed calculate timings (e.g. https://github.com/apache/incubator-nuttx/blob/master/arch/arm/src/s32k1xx/s32k1xx_flexcan.c#L393). However only having the timing from just the bitrate isn't enough you might end up with a low sample point e.g. 60% which is non-ideal.
Regarding DS-015 we participated in the network topology discussion and stated if that if there's a well defined configuration of nodes and it's topology we could help analyzing the impact of different bitrates on such a topology.
Originally posted by @PetervdPerk-NXP in #109 (comment)
I presume it should be named uavcan.can.sample_point_pct
and typed uint8[2]
, for arbitration and data segments, respectively.
We need help with supporting DSDL in:
Instead of talking about DSDL versions and stabilization of DSDL as a whole, this RFC suggests the alternative of versioning data types individually. This will ease the task of stabilization, allowing it to happen sooner, giving a more flexible way to describe compatibility between DSDL, and enabling a way to accept bit compatible data types without freezing data type signatures [#4]. Some robustness is also gained by having ways to check if single frame data types have conflicting definitions.
There is an obvious need to stabilize DSDL. Every time a message is changed every software depending on it breaks. There is also a need to not prematurely stabilize. Being stuck with badly functioning data types will be the consequence, and it won't be fixable until next major version.
With the current system (waiting for dsdl 1.0) no stabilization is realistically within reach. For every battle proven data type, there is a data type that is not yet ready as well. By keeping on adding data types when it is convenient a dsdl stabilization is further pushed in the future as well.
By accepting separate versioning of data types, these problems should be much easier to handle. The proven parts of dsdl can be stabilized while allowing rapid development of the non-stabilized parts. This also allows software that only relies on stable messages to be stabilized, this is a huge advantage for uavcan users.
The data type signatures are really great! They let you know when you're using the same data types, and even enforce this programmatically for multi frames. The problem is that when you do have a miss match, it's not trivial to find out which unit is erroneous. Separate versioning of data types give us tools to talk about the version of the messages. For instance, if a unit (outside our control) states that it sends 0.2 frames and we know that we currently accept 0.3 frames, we will be much closer to fix the problem. It will also make it possible to (non-automatically) detect different single frame transfers, this would not otherwise be noticed as no CRC is used.
There are a lot of things that can go wrong when stabilizing DSDL. By stabilizing one data type at a time we make eventual "screw ups" less possible and more handleable. By combining this with using gained knowledge from previous stabilizations to stabilize new data types, stabilization should have a much lower chance of causing headaches.
The approach to versioning is based upon the proven idea of semantic versioning but adapted to make sense for dsdl. The version information is encoded directly in the name of the file where the definition is contained such as <ID>.<Name>.<Major version>.<Minor version>.uavcan
. For example 341.NodeStatus.1.0.uavcan
Let's use the following frame as an example
#version 1.0
uint2 state
void2 reserved1
void4 reserved2
If we were to add a comment we would have to increment the minor version (this doesn't change data type signature nor bit compatibility)
#version 1.1
uint2 state # i like comments
void2 reserved1
void4 reserved2
In the same way, adding constants would only require an increment of the minor version
#version 1.2
uint2 STATE_IDLE = 0
uint2 STATE_TRANSMITTING = 1
uint2 STATE_RECEIVING = 2
uint2 STATE_ERROR = 3
uint2 state # i like comments
void2 reserved1
void4 reserved2
But removing/changing a constant would require a major version (since it breaks backward compatibility)
#version 2.0
uint2 STATE_OK = 0
uint2 STATE_STARTING = 1
uint2 STATE_ERROR = 3
uint2 state # i like comments
void2 reserved1
void4 reserved2
Changing the name of fields or constants would not retain code compatibility and will also require a major version increment.
#version 3.0
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # i like comments
void2 reserved1
void4 reserved2
Removing/editing a comment will both keep data type signature and code compatibility, thus only requiring minor version increment
#version 3.1
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # This is the status
void2 reserved1
void4 reserved2
Using new fields in a bit compatible way or changing the name of void fields only require a minor version update.
#version 3.2
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # This is the status
uint3 STATE_IDLE = 0
uint3 STATE_TRANSMITTING = 1
uint3 STATE_RECEIVING = 2
uint3 STATE_ERROR = 7
void3 state
void3 reserved
This feature should be regarded as a low impact feature. The feature itself will not change the generated code. Meaning that by treating files without version as 0.0 (and forbidding explicit version 0.0) this change will be fully backward compatible. This means that for example 341.NotStatus.uavcan
"really" means 341.NodeStatus.0.0.uavcan
, while explicitly writing 341.NodeStatus.0.0.uavcan
will result in an error.
In some way or another we will have to specify the exact version the data type is dependent on. One way to do this would be as following
@use Command version 0.2
Command[<=15] commands
Another alternative would be
Command.0.2[<=15] commands
The following rules must be adopted
Hi
We are trying to use UAVCAN (libcanard) in our project. We found some inconsistency with uavcan.equipment.safety message - most of other messages uses 0 for nominal state and all bits set to indicate error (uavcan.protocol.NodeStatus.health - 0b00 for HEALTH_OK, 0b11 for HEALTH_CRITICAL, etc.). The same is valid for undefined values (maximum value for unsigned integer, NaN for float (in both cases all bits set to 1)). For uavcan.equipment.safety message this approach results in FULLY_ARMED as default value.
I propose:
#
# This message represents the system arming status.
# Some nodes may refuse to operate unless the system is fully armed.
#
uint8 STATUS_DISARMED = 0
uint8 STATUS_FULLY_ARMED = 254
uint8 STATUS_MALFUNCTION = 255 # or STATUS_CRASHED
uint8 status
Or to flip values to 0 = FULLY_ARMED and 255 = DISARMED
We are trying to initialize all our UAVCAN buffers and structs with 0xFF to make it more "errorproof" by setting it to safe, detectable, bug indicating default value (e.g. 127%).
Is there a reason that every si/sample
type re-implements the corresponding si/unit
type, instead of combining the timestamp with the corresponding si/unit/
type?
Originally posted by @JacobCrabill in #81 (comment)
Whether the uavcan will add some standard data type for the ECU equipment,like engine RPM,TPS,oil pressure e.g .
candela is missing from our si namespace.
Note: This RFC is still highly incomplete. As long as the [WIP] tag is in place I will edit this issue rather freely
Let's assume #35 lands. DSDL is now pretty great, we even have a way to talk about versions which make it trivial to see what kind of versions that are compatible. The problem is that the implementations don't care. They will see two data types with different signature even when they only differ a minor version and should be regarded as compatible.
This RFC will attempt to solve this issue by using the same data type signature for all compatible frames.
When the dsdl is compiled for a data type, it should always use the data type signature of the oldest compatible message. This is the version on the form @version <MAJOR>.0.0
where <MAJOR>
matches the data type under compilation.
The exception is not yet stabilized messages (major version 0). For those the dsdl compiler should use the data signature of the message itself.
This will require that all versions with the current major version is kept in the dsdl file. Several data type versions in same file is already accepted if we accept the use <DataType> version x.y.z
from #35.
Let's use the same frame as from #35
This makes the file initialy looking like
@version 1.0.0
uint2 state
void2 reserved1
void4 reserved2
But after updating the version a couple of times, it quickly looks like
@version 1.0.0
uint2 state
void2 reserved1
void4 reserved2
@version 1.0.1
uint2 state # i like comments
void2 reserved1
void4 reserved2
@version 1.0.2
uint2 STATE_IDLE = 0
uint2 STATE_TRANSMITTING = 1
uint2 STATE_RECEIVING = 2
uint2 STATE_ERROR = 3
uint2 state # i like comments
void2 reserved1
void4 reserved2
When the major version is incremented, old versions may be removed (unless they're depended upon by other frames)
@version 2.0.0
uint2 STATE_OK = 0
uint2 STATE_STARTING = 1
uint2 STATE_ERROR = 3
uint2 state # i like comments
void2 reserved1
void4 reserved2
When updating to next major version, the old on is scrapped as well
@version 3.0.0
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # i like comments
void2 reserved1
void4 reserved2
With the last additions, this ends up looking like
@version 3.0.0
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # i like comments
void2 reserved1
void4 reserved2
@version 3.0.1
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # This is the status
void2 reserved1
void4 reserved2
@version 3.1.0
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # This is the status
uint3 STATE_IDLE = 0
uint3 STATE_TRANSMITTING = 1
uint3 STATE_RECEIVING = 2
uint3 STATE_ERROR = 7
void3 state
void3 reserved
Assuming the use <DataType> version x.y.z
syntax from #35 is accepted. If a message depend on
2.0.0 after upgrading to 3.0.0 the dsdl file will look as following.
@version 2.0.0
uint2 STATE_OK = 0
uint2 STATE_STARTING = 1
uint2 STATE_ERROR = 3
uint2 state # i like comments
void2 reserved1
void4 reserved2
@version 3.0.0
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # i like comments
void2 reserved1
void4 reserved2
@version 3.0.1
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # This is the status
void2 reserved1
void4 reserved2
@version 3.1.0
uint2 STATUS_OK = 0
uint2 STATUS_STARTING = 1
uint2 STATUS_ERROR = 3
uint2 status # This is the status
uint3 STATE_IDLE = 0
uint3 STATE_TRANSMITTING = 1
uint3 STATE_RECEIVING = 2
uint3 STATE_ERROR = 7
void3 state
void3 reserved
This can be implemented in a backward compatible way. If #35 is accepted, no data types will list its version and thus be in version 0.0.0. If this feature is accepted before any data type increments its version to 1.1.0 (is stabilized and improved upon). This feature will be fully backward compatible.
This should be pretty equivalent in implementation overhead as #4 while solving the same problem in (what I believe is) a cleaner way.
The alternative proposed in #4 could be used instead. But if the addition of seperate versioning lands, i feel like this proposal is a more hollistic approach.
Question 1: In the file 1092.BatteryInfo.uavcan
I found that float16 remaining_capacity_wh # [Watt hours] Will be increasing during charging
float16 full_charge_capacity_wh # [Watt hours] Predicted battery capacity when it is fully charged. Falls with aging
The units of remaining_capacity_wh and full_charge_capacity_wh are Wh. Wh will produce a larger error. My suggestion here is to use Ah.
Question 2: In the 1091.CircuitStatus.uavcan file
In line 13 uint8 ERROR_FLAG_UNDERCURRENT = 8; What is the concept of undercurrent? The battery industry does not have this concept. I don’t know if I can explain what it means.
Rename reg.drone.srv.common.Arming
and its members into something more generic, leaving the semantics unchanged.
Context: https://forum.uavcan.org/t/service-readiness-level/967
Due to the renaming of the repository, all previous works with UAVCAN are now broken as https://github.com/UAVCAN/dsdl doesn't exist anymore.
That wasn't a nice move considering that most of UAVCAN system are on v0 ...
https://pycyphal.readthedocs.io/en/stable/pages/demo.html
that demo call for sirius_cyber_corp dsdl
but its no where to be found in the git, am I missing something important?
The specification introduces the term public regulated data type definition and says that such definitions are maintained by the UAVCAN specification maintainers. Renaming this repository would help people realize that:
Are there better ideas for the new name?
Paging @thirtytwobits @kjetilkjeka
On several occasions faulty changes have been submitted to master. A CI setup would have allowed to weed out such issues.
Had a suggestion to include all the individual cell voltages of the pack on the bms status (https://github.com/UAVCAN/public_regulated_data_types/blob/master/reg/drone/service/battery/Status.0.1.uavcan) . I believe it would help with
Originally posted by @echoGee in #81 (comment)
My company uses Dynamixel Pro servos for actuation of thrust vectoring in a UAV. These servos have advanced status fields like temperature, voltage, and some other fields. I want to create a new actuator status message: 1012.AdvancedStatus.uavcan
, which contains these fields.
It is expected that some data types will require modifications affecting their signature but not their binary layout. E.g. a message containing a voidX
definition may require an update so that the unused padding bits will be replaced with an actual field. Such a change does not affect binary compatibility, hence it makes sense to retain the DSDL signature unchanged.
For this purpose, the following DSDL directive may be added:
@signature <value>
Example:
@signature 0x12345678
The servo setpoint should command the target position, target velocity, and the force/torque limit using only reg.udral.physics.dynamics.DoF2nd
or a similar generic type.
As the ambiguous timestamp value is overflowing, none of its values can be reserved for special purposes; hence, the following is a mistake:
We may need to sacrifice one bit to make the value optional, like:
uint27 OVERFLOW_PERIOD_us = 83886080
truncated uint23[<=1] decamicrosecond
The documentation for ESCs and Servos (and the DS-15 standard) mentions the use of actuator groups and setpoint/command types (i.e. Power, Speed, Position, etc.). The setpoints available under reg.drone.service.actuator
have no references to these - only a scalar or vector array of float16's.
Am I missing something, or has that part of DS-15 not been implemented yet?
The need for this feature is still unclear, but it's worth considering.
An obvious and rather direct approach is to define a message type containing a raw block of bytes with encoded message. The message itself could be encoded in one of the existing self-defining protocol formats, e.g. Google Protobuf, BSON, etc.
Example:
void1
uint7 RECIPIENT_BROADCAST = 0
uint7 recipient
Name name
Encoding encoding
uint8[<=1024] payload
Where Name
:
void2
uint8[<64] name
Encoding
:
uint8 FORMAT_GOOGLE_PROTOBUF = 0
# Other formats...
uint8 format
A similar approach can be used for self-defining service calls.
Archive the vendor-specific DSDL repo, update the README file here to indicate that this repository is supposed to contain all public definitions, both standard and vendor-specific.
Repo to be archived: https://github.com/UAVCAN/vendor-specific-dsdl
uavcan.equipment.udp
should be extended to 8 bytes to support the EUI-64 format.(this issue is related to my ongoing experimentation with Yukon)
See https://forum.uavcan.org/t/alternative-transport-protocols-in-uavcan/324/34?u=pavel.kirienko
This affects uavcan.node.port.*
(currently v0.1)
I suggest adding this message to the standard
uavcan.equipment.power.GenericBatteryInfo
id = 1093
#
# Generic battery info.
#
uint16 battery_id #can be freely assigned by the user, but must be unique within a system
float16 voltage
float16 current
float16 charge_consumed_mAh
uint8 STATUS_FLAG_ERROR_OVERVOLTAGE = 1
uint8 STATUS_FLAG_ERROR_UNDERVOLTAGE = 2
uint8 STATUS_FLAG_ERROR_OVERCURRENT = 4
uint8 STATUS_FLAG_ERROR_UNDERCURRENT = 8
uint8 status_flags
Here, battery_id should not match battery_id of the BatteryInfo message. That is, every battery should have it's own, unique battery_id, but every battery is free to decide which message, GenericBatteryInfo or BatteryInfo, it wants to emit (or both).
Reasons for that additional message: 13th post here ArduPilot/ardupilot#6527
In principle, I would think that the existing BatteryInfo message could need a revision. First, I think it would be better named SmartBatteryInfo. Also, I think the suggested use of battery_id isn't suitable. It should be unique within each system, of course, but otherwise the user may assign it as she/he wants. That is, she/he may number ALL her/his batteries once and for all, more along the lines of a GUID. Anything else would not be very practical. E.g., if the primary battery would have to have battery_id = 0, as currently suggested, every change of a battery would need fumbling around with the id's. How nasty. In that light, a range of unit8 for battery_id might be quite narrow.
I found it to be often useful to have small fixed-size arrays for representation of arbitrary arrays and matrices without the array prefix:
uavcan.primitive.array.Real16x2
... Real16x9
uavcan.primitive.array.Real32x2
... Real32x9
uavcan.primitive.array.Real64x2
... Real64x9
That would be 24 new types in total.
@thirtytwobits should we add this to the core set?
Status doesn't allow for reporting any fix types better then 3D fix. This is a problem as there are significant differences between 3D, DGPS, RTK Float, RTK Fixed types. (As well as not allowing for future reporting of a fixed base status).
The accuracy estimates can be used for comparing which GPS to use, however there are several issues with trying to use it in this manner:
UAVCAN will support CAN FD in the future (possibly in v1.1) in a fully backward-compatible way. The feature has not been included in v1.0 due to low demand.
See this thread: https://groups.google.com/d/msg/uavcan/Er2ghsqumVs/1671vlOtCgAJ
TL;DR: we're going to add an alternative connector option that will be compatible with the CiA 303 DB9 connector specification (the de-facto industry standard D-Sub connector for CAN).
The power supply voltage in this pinout is ranging from +18 to +30 VDC, the nominal is +24 VDC. This is unlike the currently used JST GH, where we're supplying +5 VDC.
This proposition doesn't rule out the possible emergence of other connector types in the future.
Here's the CiA 303 document: 303_1v01080001.pdf
The original intent was to benefit from the strongly typed uavcan.si
namespace but the experience indicates that it makes the types more complex with little actual benefit. I propose replacing the segregated translational/rotational types with generalized types that contain native float32
-typed fields instead of referring to the uavcan.si
namespace.
This change will not affect wire compatibility.
why [<=60]?
why not 59, or 66? Even 64 would be better frame usage than 60
protocol doesn't really make much sense, right. Especially if 0 is mavlink. 0 = default should be rather something like UNDEFINED/GENERIC/TRANSPARENT or whatever it is named. What instead would be seriously needed is some possibility to send meta data, such as baudrate, clock rate, etc. pp. See gps example in https://www.youtube.com/watch?v=Sw24wAIoemA.
my 2 c :)
The data types inside this namespace actually model the magnetic flux density, so the namespace should be renamed and the old definitions deprecated.
uavcan.pub.*.prio
with 0 for the highest priority and 7 for the lowest.
As a reminder, the version 1.0 of the specification has not yet been released. Before the release, we need to walk over all of the messages defined in the namespace uavcan.equipment.
to weed out the remaining weirdness and inconsistencies.
uavcan.equipment.ahrs.MagneticFieldStrength3
(@jschall suggested to make the message timestamped, I agree; more on this in the chat room https://gitter.im/UAVCAN/general)uavcan.equipment.range_sensor
uavcan.equipment.safety
uavcan.equipment.power.PrimaryPowerSupplyStatus
_id
fields defined in the standard messages. #33 is a great example how much confusion can be caused by the omission of important data points from the specification.The uavcan.can.iface
standard register specifies a key where you can change can interface to be used.
# REGISTER NAME PATTERN TYPE FLAGS RECOMMENDED DEFAULT
# uavcan.can.iface string mutable, persistent implementation-defined
# uavcan.can.iface is only relevant for software nodes or nodes that are capable of using different CAN interfaces.
# The value is a space-separated list of CAN interface names to use. The name format is implementation-defined
# (for example, "can0").
However the user cannot derive which CAN interfaces are available, in the worst case this would yield a misconfiguration and the node will not be available anymore on the bus.
To solve this I have two potential solutions:
uavcan.can.ifaces
which is not mutable (i.e. read-only) and exposes a list of available interfaces.uavcan.can.iface
from string to a bool array i.e. bool[n]
where n
indicates the number of CAN interfaces and bool[0]
correspond to can0
etc, then user can then easily select one or more CAN interfaces to use and this minimize the memory footprint to implement this features as well.The specification of joule in this message is ambiguous because it is up to the implementer to use a voltage (current battery voltage, nominal voltage, max battery voltage (number of cells * max cell voltage)).
Energy and full energy could use different voltages in the joule calculation, thus this can't be divided to get the state of charge.
We need to have this script transformed into a standalone reusable DSDL linter:
https://github.com/UAVCAN/public_regulated_data_types/blob/master/verify
Business requirements:
\r
(carriage return).I am not sure where the script should be located; could be the PyDSDL repo or just a separate gist?
Original comment: https://github.com/UAVCAN/public_regulated_data_types/pull/67/files/acb48c15288510bffea3797d76e3eca21d6413dc#r322079388
Register name pattern | Flags | Register value type | Purpose |
---|---|---|---|
uavcan.node.description |
MP | String | Human-readable verbose description of this specific node defined by the integrator (not vendor), empty by default |
uavcan.cookie |
MP | String | Arbitrary data stored by an external autoconfiguration authority, empty by default |
uavcan.favicon |
IP | Boolean[2025] | 45x45 row-major monochrome binary image, top-left pixel first, 0=black, 1=white, set by vendor |
uavcan.sub.<name>.id |
MP | Natural16 | Subscription subject-ID, set by integrator |
uavcan.sub.<name>.type |
IP | String | Subscription type name, set by vendor |
uavcan.pub.<name>.id |
MP | Natural16 | Publication subject-ID, set by integrator |
uavcan.pub.<name>.type |
IP | String | Publication type name, set by vendor |
uavcan.srv.<name>.id |
MP | Natural16 | Server service-ID, set by integrator |
uavcan.srv.<name>.type |
IP | String | Server service type name, set by vendor |
uavcan.cln.<name>.id |
MP | Natural16 | Client service-ID, set by integrator |
uavcan.cln.<name>.type |
IP | String | Client service type name, set by vendor |
Where <name>
is [a-zA-Z_][a-zA-Z0-9_]*
(POSIX ERE).
Specify that it is not required but recommended that changes take effect immediately.
Later, additional patterns can be added like uavcan.pub.<name>.period
.
This is where it should be defined:
Relevant discussions:
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.