Git Product home page Git Product logo

domain_bridge's Introduction

About

The Robot Operating System (ROS) is a set of software libraries and tools that help you build robot applications. From drivers to state-of-the-art algorithms, and with powerful developer tools, ROS has what you need for your next robotics project. And it's all open source. Full project details on ROS.org

Getting Started

Looking to get started with ROS? Our installation guide is here. Once you've installed ROS start by learning some basic concepts and take a look at our beginner tutorials.

Join the ROS Community

Community Resources

Developer Resources

Project Resources

ROS is made possible through the generous support of open source contributors and the non-profit Open Source Robotics Foundation (OSRF). Tax deductible donations to the OSRF can be made here.

domain_bridge's People

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

Watchers

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

domain_bridge's Issues

Different FastDDS XML configuration files for the two sides of the domain bridge

Hello all

I have a specific case I need to solve, for which I need the two sides of the domain bridge to connect to different machines.
I'm using FastDDS whitelisting setup with an XML file following the documentation here.

My issue is that the two ROS2 nodes, for example gateway_0 and gateway_1 use the same XML file. I want to specify one file for gateway_0 and another for gateway_1, but am not sure how to proceed.

What I'm looking for to start on this issue is the code location where the nodes are created to understand more, and maybe at this location I can do something to switch from the two XML files.

Any help on the subject is appreciated!
Victor

Service bridge tests fail with non-default RMW

To reproduce, run the service tests with the env variable RMW_IMPLEMENTATION set to something other than rmw_connextdds, for example rmw_fastrtps_cpp or rmw_connextdds:

RMW_IMPLEMENTATION=rmw_fastrtps_cpp colcon test --event-handlers console_direct+ --ctest-args -R test_domain_bridge_service

We see the following test failures:

13: Test timeout computed to be: 60
13: -- run_test.py: invoking following command in '/home/jacob/ws/domain_bridge/build/domain_bridge/test':
13:  - /home/jacob/ws/domain_bridge/build/domain_bridge/test/test_domain_bridge_services --gtest_output=xml:/home/jacob/ws/domain_bridge/build/domain_bridge/test_results/domain_bridge/test_domain_bridge_services.gtest.xml
13: Running main() from gmock_main.cc
13: [==========] Running 1 test from 1 test suite.
13: [----------] Global test environment set-up.
13: [----------] 1 test from TestDomainBridgeServices
13: [ RUN      ] TestDomainBridgeServices.bridge_service
13: /home/jacob/ws/domain_bridge/src/domain_bridge/test/domain_bridge/test_domain_bridge_services.cpp:139: Failure
13: Value of: poll_condition([cli]() {return cli->service_is_ready();}, 3s)
13:   Actual: false
13: Expected: true
13: /home/jacob/ws/domain_bridge/src/domain_bridge/test/domain_bridge/test_domain_bridge_services.cpp:145: Failure
13: Value of: poll_condition([&got_request]() {return got_request.load();}, 3s)
13:   Actual: false
13: Expected: true
13: /home/jacob/ws/domain_bridge/src/domain_bridge/test/domain_bridge/test_domain_bridge_services.cpp:146: Failure
13: Expected equality of these values:
13:   future.wait_for(3s)
13:     Which is: 4-byte object <01-00 00-00>
13:   std::future_status::ready
13:     Which is: 4-byte object <00-00 00-00>
13: [  FAILED  ] TestDomainBridgeServices.bridge_service (9045 ms)
13: [----------] 1 test from TestDomainBridgeServices (9045 ms total)
13: 
13: [----------] Global test environment tear-down
13: [==========] 1 test from 1 test suite ran. (9045 ms total)
13: [  PASSED  ] 0 tests.
13: [  FAILED  ] 1 test, listed below:
13: [  FAILED  ] TestDomainBridgeServices.bridge_service

We should probably consider running tests for all available RMWs (similar to some of the core ROS 2 packages).

Windows support

I don't think the domain_bridge package currently builds on Windows. We should resolve these build issues.

It would also be nice to enable Windows CI via the GitHub workflow. If this turns out to be difficult, we can always verify Windows support by trigger CI at ci.ros2.org.

Integrate domain bridge with rclcpp_components

We should leverage the existing rclcpp_components framework to allow the domain bridge to be loaded into a container. This would allow the bridge and all other nodes to be run in the same process, ideally reducing latency.

Bridging from/to the same domain ID

I noticed a degenerate case if we configure a topic bridge from and to the same domain ID. In this case, we enter a feedback loop where the domain bridge subscribes to itself, resulting in the publication of many duplicate messages.

Here's a simple configuration that reproduces the issue:

name: my_bridge
from_domain: 2
to_domain: 2
topics:
  chatter:
    type: std_msgs/msg/String

We can trigger a feedback loop by publishing a single message to the /chatter topic:

ROS_DOMAIN_ID=2 ros2 topic pub -1 /chatter std_msgs/msg/String "{data: 'hello'}"

And we can see a flood of messages on the /chatter topic:

ROS_DOMAIN_ID=2 ros2 topic echo /chatter

I think we should guard against this case. If a user tries to create a bridge with the same from/to domain ID, then log a warning and do not bridge the topic.

Add support for ROS2 Iron Irwini (-Wdeprecated-declarations)

Hello, I tried to compile the gateway node in ROS2 Iron Irwini, which lead to -Wdeprecated-declarations warnings, see below for full output.
In itself, not blocking, but would be good to support this.

#8 28.71 --- stderr: domain_bridge
#8 28.71 In file included from /home/workspace/src/domain_bridge/include/domain_bridge/domain_bridge.hpp:166,
#8 28.71                  from /home/workspace/src/domain_bridge/src/domain_bridge.cpp:21:
#8 28.71 /home/workspace/src/domain_bridge/include/domain_bridge/service_bridge_impl.inc: In instantiation of ‘void domain_bridge::DomainBridge::bridge_service(const string&, size_t, size_t, const domain_bridge::ServiceBridgeOptions&) [with ServiceT = std_srvs::srv::Trigger; std::string = std::__cxx11::basic_string<char>; size_t = long unsigned int]’:
#8 28.71 /home/workspace/src/domain_bridge/src/domain_bridge.cpp:76:57:   required from here
#8 28.71 /home/workspace/src/domain_bridge/include/domain_bridge/service_bridge_impl.inc:104:58: warning: ‘typename rclcpp::Client<ServiceT>::SharedPtr rclcpp::Node::create_client(const string&, const rmw_qos_profile_t&, rclcpp::CallbackGroup::SharedPtr) [with ServiceT = std_srvs::srv::Trigger; typename rclcpp::Client<ServiceT>::SharedPtr = std::shared_ptr<rclcpp::Client<std_srvs::srv::Trigger> >; std::string = std::__cxx11::basic_string<char>; rmw_qos_profile_t = rmw_qos_profile_s; rclcpp::CallbackGroup::SharedPtr = std::shared_ptr<rclcpp::CallbackGroup>]’ is deprecated: use rclcpp::QoS instead of rmw_qos_profile_t [-Wdeprecated-declarations]
#8 28.71   104 |   auto client = from_domain_node->create_client<ServiceT>(
#8 28.71       |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
#8 28.71   105 |     resolved_service_name,
#8 28.71       |     ~~~~~~~~~~~~~~~~~~~~~~                                
#8 28.71   106 |     rmw_qos_profile_services_default,
#8 28.71       |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                     
#8 28.71   107 |     options.callback_group());
#8 28.71       |     ~~~~~~~~~~~~~~~~~~~~~~~~~                             
#8 28.71 In file included from /opt/ros/iron/include/rclcpp/rclcpp/node.hpp:1600,
#8 28.71                  from /opt/ros/iron/include/rclcpp/rclcpp/executors/single_threaded_executor.hpp:28,
#8 28.71                  from /home/workspace/src/domain_bridge/src/domain_bridge.cpp:17:
#8 28.71 /opt/ros/iron/include/rclcpp/rclcpp/node_impl.hpp:157:1: note: declared here
#8 28.71   157 | Node::create_client(
#8 28.71       | ^~~~
#8 28.71 In file included from /home/workspace/src/domain_bridge/include/domain_bridge/domain_bridge.hpp:166,
#8 28.71                  from /home/workspace/src/domain_bridge/src/domain_bridge.cpp:21:
#8 28.71 /home/workspace/src/domain_bridge/include/domain_bridge/service_bridge_impl.inc:137:52: warning: ‘typename rclcpp::Service<ServiceT>::SharedPtr rclcpp::Node::create_service(const string&, CallbackT&&, const rmw_qos_profile_t&, rclcpp::CallbackGroup::SharedPtr) [with ServiceT = std_srvs::srv::Trigger; CallbackT = const domain_bridge::DomainBridge::bridge_service<std_srvs::srv::Trigger>(const string&, size_t, size_t, const domain_bridge::ServiceBridgeOptions&)::<lambda(std::shared_ptr<rclcpp::Service<std_srvs::srv::Trigger> >, std::shared_ptr<rmw_request_id_s>, std::shared_ptr<std_srvs::srv::Trigger_Request_<std::allocator<void> > >)>&; typename rclcpp::Service<ServiceT>::SharedPtr = std::shared_ptr<rclcpp::Service<std_srvs::srv::Trigger> >; std::string = std::__cxx11::basic_string<char>; rmw_qos_profile_t = rmw_qos_profile_s; rclcpp::CallbackGroup::SharedPtr = std::shared_ptr<rclcpp::CallbackGroup>]’ is deprecated: use rclcpp::QoS instead of rmw_qos_profile_t [-Wdeprecated-declarations]
#8 28.71   137 |     return to_domain_node->create_service<ServiceT>(
#8 28.71       |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
#8 28.71   138 |       service_remapped,
#8 28.71       |       ~~~~~~~~~~~~~~~~~                             
#8 28.71   139 |       handle_request,
#8 28.71       |       ~~~~~~~~~~~~~~~                               
#8 28.71   140 |       rmw_qos_profile_services_default,
#8 28.71       |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~             
#8 28.71   141 |       options.callback_group());
#8 28.71       |       ~~~~~~~~~~~~~~~~~~~~~~~~~                     
#8 28.71 In file included from /opt/ros/iron/include/rclcpp/rclcpp/node.hpp:1600,
#8 28.71                  from /opt/ros/iron/include/rclcpp/rclcpp/executors/single_threaded_executor.hpp:28,
#8 28.71                  from /home/workspace/src/domain_bridge/src/domain_bridge.cpp:17:
#8 28.71 /opt/ros/iron/include/rclcpp/rclcpp/node_impl.hpp:190:1: note: declared here
#8 28.71   190 | Node::create_service(
#8 28.71       | ^~~~
#8 28.71 ---
#8 28.71 Finished <<< domain_bridge [27.1s]
#8 28.74 
#8 28.74 Summary: 1 package finished [27.5s]
#8 28.74   1 package had stderr output: domain_bridge

Support actions

Similar to topics and services, it would be nice to also support ROS actions.

Since actions are built upon topics and services, the bridge implementation will depend on how we decide to bridge services (#10).

Allow bi-directional topic bridging

We should add an option to enable bi-directional communication for bridged topics.

This could be done on a per-topic basis in the yaml config, or by grouping topics into "one-way" and "bi-directional" categories.

One topic maps to multiple domains

Howdy, I'd like to ask for some thoughts of mapping one topic to different domains. For example, I want topic /topic_a from ROS_DOMAIN_ID=0 broadcast to ROS_DOMAIN_ID=[1,2,3,4...] .

What I tried:
a). in the .yaml config file, I just duplicate this topic like

  /topic_a:
    from_domain: 0
    to_domain: 1
    type: std_msgs/msg/Int16
  /topic_a:
    from_domain: 0
    to_domain: 2
    type: std_msgs/msg/Int16
  /topic_a:
    from_domain: 0
    to_domain: 3
    type: std_msgs/msg/Int16
...

And surprisingly it worked! We are able to duplicate the key in .yaml file and domain_bridge follows this.

b). a more controllable way, I desire to input the bridge content from code (Python, Cpp). But to generate the .yaml file, we need to make the data as dictionary. We cannot duplicate the key in dictionary. And here my question is what is a good way to make this happen in scripts, in stead of hand code the domain bridge.

Thanks!

Flaky end-to-end tests

Some of the tests in test_domain_bridge_end_to_end.cpp fail occasionally when running colcon test:

- domain_bridge.TestDomainBridgeEndToEnd compress_mode
  <<< failure message
    /home/rebecca/ws/domain_bridge_ws/domain_bridge/test/domain_bridge/test_domain_bridge_end_to_end.cpp:216
    Value of: poll_condition([&got_message]() {return got_message.load();}, 3s)
      Actual: false
    Expected: true
  >>>

I've seen messages like this for the compress_mode, decompress_mode, and remap_topic_name tests.

Support services

Currently, the domain bridge only supports topics, but it would be great to support services as well.

Analogous to how topics are bridged by creating a subscription/publisher pair, services could be bridged by creating a service/client pair that forwards calls from clients in one domain to services in another domain. For example, a service /add_two_ints could be bridged from domain ID 1 to domain ID 2 by

  1. Waiting for a /add_two_ints service to be offered in domain ID 2
  2. When the service is ready, create an equivalent a service in the bridge, but on domain ID 1
  3. Also create a service client for domain ID 2
  4. Whenever a request comes in on domain ID 1, forward it to domain ID 2 using the bridges service client
  5. When a response comes back on domain ID 2, forward it to domain ID 1.

This requires the service and client created by the bridge to communicate within the same process (e.g. using a shared resource).

I don't think we should be concerned with supporting multiple services by the same name, since that isn't well supported in ROS itself.

One critical blocker for this feature may be type support. Unlike topic messages, services do not have equivalent APIs readily available for working with serialized data. This means we may find it difficult to forward requests/responses without knowing the service types at compile time.

QoS overriding

#5 enables automatic QoS selection based on available publishers, but it would be nice to have the option to override the QoS used for a particular topic.

We could achieve this by adding to the TopicBridgeOptions class and exposing YAML configuration points.

In particular, it is already documented in the design doc that history and depth policies should be configurable since they can not be queried from publishers at runtime. Currently, they are defaulting to KEEP_LAST and 10.

Branch name change for Cmake command ```ExternalProject_Add```

I want use ExternalProject_Add command for automatic download and build for my_project.

But default branch name main , can you change with master.

if you not change branch name cmake not support $GIT_BRANCH (I don't know ) command just $GIT_TAG

domain_bridge indiriliyor...
Cloning into 'domain_bridge_lib'...
fatal: invalid reference: master
CMake Error at /home/harun/titra_work/task1_domain2domain/domain2domain/build/doman2domain/domain_bridge_lib-prefix/tmp/domain_bridge_lib-gitclone.cmake:40 (message):
  Failed to checkout tag: 'master'


gmake[2]: *** [CMakeFiles/domain_bridge_lib.dir/build.make:98: domain_bridge_lib-prefix/src/domain_bridge_lib-stamp/domain_bridge_lib-download] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:105: CMakeFiles/domain_bridge_lib.dir/all] Error 2
gmake: *** [Makefile:146: all] Error 2
cmake_minimum_required(VERSION 3.8)
include(FetchContent)
include(ExternalProject)

project(
        my_project
        VERSION 1.0
        DESCRIPTION "my_project"
)

message("domain_bridge indiriliyor...")

ExternalProject_Add(
    domain_bridge_lib
    GIT_REPOSITORY https://github.com/ros2/domain_bridge.git
    GIT_TAG 0.5.0
    BUILD_COMMAND $(MAKE) domain_bridge
    STEP_TARGETS build
)

humble,There was an error compiling

Ubuntu22.04 Humble

Starting >>> domain_bridge
--- stderr: domain_bridge
/home/fang/hiway_ws/build/domain_bridge/rosidl_typesupport_fastrtps_c/domain_bridge/msg/detail/compressed_msg__type_support_c.cpp: In function ‘bool _CompressedMsg__cdr_serialize(const void*, eprosima::fastcdr::Cdr&)’:
/home/fang/hiway_ws/build/domain_bridge/rosidl_typesupport_fastrtps_c/domain_bridge/msg/detail/compressed_msg__type_support_c.cpp:59:9: error: ‘class eprosima::fastcdr::Cdr’ has no member named ‘serializeArray’; did you mean ‘serialize_array’?
59 | cdr.serializeArray(array_ptr, size);
| ^~~~~~~~~~~~~~
| serialize_array
/home/fang/hiway_ws/build/domain_bridge/rosidl_typesupport_fastrtps_c/domain_bridge/msg/detail/compressed_msg__type_support_c.cpp: In function ‘bool _CompressedMsg__cdr_deserialize(eprosima::fastcdr::Cdr&, void*)’:
/home/fang/hiway_ws/build/domain_bridge/rosidl_typesupport_fastrtps_c/domain_bridge/msg/detail/compressed_msg__type_support_c.cpp:87:9: error: ‘class eprosima::fastcdr::Cdr’ has no member named ‘deserializeArray’; did you mean ‘deserialize_array’?
87 | cdr.deserializeArray(array_ptr, size);
| ^~~~~~~~~~~~~~~~
| deserialize_array
gmake[2]: *** [CMakeFiles/domain_bridge__rosidl_typesupport_fastrtps_c.dir/build.make:91: CMakeFiles/domain_bridge__rosidl_typesupport_fastrtps_c.dir/rosidl_typesupport_fastrtps_c/domain_bridge/msg/detail/compressed_msg__type_support_c.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:310: CMakeFiles/domain_bridge__rosidl_typesupport_fastrtps_c.dir/all] Error 2
gmake[1]: *** Waiting for unfinished jobs....
gmake: *** [Makefile:146: all] Error 2

Failed <<< domain_bridge [8.80s, exited with code 2]

test_msgs problem

Hello I build my workspace but I got error.

can you remove test_msgs for default build ?

CMake Error at CMakeLists.txt:143 (find_package):
  By not providing "Findtest_msgs.cmake" in CMAKE_MODULE_PATH this project
  has asked CMake to find a package configuration file provided by
  "test_msgs", but CMake did not find one.

  Could not find a package configuration file provided by "test_msgs" with
  any of the following names:

    test_msgsConfig.cmake
    test_msgs-config.cmake

  Add the installation prefix of "test_msgs" to CMAKE_PREFIX_PATH or set
  "test_msgs_DIR" to a directory containing one of the above files.  If
  "test_msgs" provides a separate development package or SDK, be sure it has
  been installed.  

Use generic pub/sub from rclcpp

Now that implementation for generic publishers and subscriptions exists in rclcpp, we can remove the duplicate code from domain_bridge.

Enabling ROS 2 Security

Hi,
I want to connect two domains, one of which is secured with sros2. I created a simple demo that should connect secured demo_nodes_cpp/talker through domain_bridge/domain_bridge on domain ID=0 to unsecured demo_nodes_cpp/listener on domain ID=1.

First, generate keys and certificates as in the sros2 tutorial. We will use /talker_listener/talker enclave for bridge, as by default it doesn't apply any access control and will work with any nodes and topics.

cd ~/sros2_demo
ros2 security create_keystore demo_keystore
ros2 security create_enclave demo_keystore /talker_listener/talker
ros2 security create_enclave demo_keystore /talker_listener/listener

Terminal 1:

export ROS_DOMAIN_ID=0
export ROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystore
export ROS_SECURITY_ENABLE=true
export ROS_SECURITY_STRATEGY=Enforce
ros2 run demo_nodes_cpp talker --ros-args --enclave /talker_listener/talker

Terminal 2:

export ROS_DOMAIN_ID=1
ros2 run demo_nodes_cpp listener

Terminal 3:

export ROS_DOMAIN_ID=0
export ROS_SECURITY_KEYSTORE=~/sros2_demo/demo_keystore
export ROS_SECURITY_ENABLE=true
export ROS_SECURITY_STRATEGY=Enforce
ros2 run domain_bridge domain_bridge bridge.yaml --ros-args --enclave /talker_listener/talker

bridge.yaml:

name: my_domain_bridge
topics:
  chatter:
    from_domain: 0
    to_domain: 1
    type: std_msgs/msg/String

Expected result

Bridge receives secured messages and publishes them as unsecured.

Actual result

Bridge crashes with following logs:

[INFO] [1686655410.275770214] [rcl]: Found security directory: /home/ros/sros2_demo/demo_keystore/enclaves/talker_listener/talker
[INFO] [1686655410.276668597] [rcl]: Found security directory: /home/ros/sros2_demo/demo_keystore/enclaves

>>> [rcutils|error_handling.c:108] rcutils_set_error_state()
This error state is being overwritten:

  'couldn't find all security files!, at ./src/participant.cpp:274, at ./src/rcl/node.c:263'

with this new error message:

  'rcl node's rmw handle is invalid, at ./src/rcl/node.c:415'

rcutils_reset_error() should be called after error handling to avoid this.
<<<
[ERROR] [1686655410.277115123] [rcl]: Failed to fini publisher for node: 1
terminate called after throwing an instance of 'rclcpp::exceptions::RCLError'
  what():  failed to initialize rcl node: rcl node's rmw handle is invalid, at ./src/rcl/node.c:415
[ros2run]: Aborted

Running any other node in Terminal 3 (e.g. ros2 run demo_nodes_cpp listener --ros-args --enclave /talker_listener/talker) works fine.

Is this error in my setup, or is the security not working with the domain_bridge yet? The "Security" section in the design doc only has "TODO" and last mention was on #1 over two years ago with no follow ups.

If I understand correctly, it should not work out of the box, as generated keystore depends on the domain ID, so even if it could somehow connect secure to insecure domain, it could be much less obvious how to connect two separately secured domains (we set keystore location through env variable).

Domain bridge crashes with Connext

I've tried using the bridge with rmw_connext_cpp and rmw_connextdds, but the program crashes when using either of them.

[D0003|Pub(80000008)|T=rt/chatter|CREATE Writer]DDS_DeadlineQosPolicy_is_consistentI:inconsistent QoS policy: period
[D0003|Pub(80000008)|T=rt/chatter|CREATE Writer]DDS_DataWriterQos_is_consistentI:inconsistent QoS policy: deadline
[D0003|Pub(80000008)|T=rt/chatter|CREATE Writer]DDS_Publisher_create_datawriter_disabledI:ERROR: Inconsistent QoS
[ERROR] [1617216731.741343399] [rmw_connextdds]: failed to create DDS writer
[ERROR] [1617216731.741481113] [rmw_connextdds]: failed to allocate RMW_Connext_Publisher
[ERROR] [1617216731.741494351] [rmw_connextdds]: failed to create RMW publisher
terminate called after throwing an instance of 'rclcpp::exceptions::RCLError'
  what():  could not create publisher: Handle's typesupport identifier (rosidl_typesupport_cpp) is not supported by this library, at /home/jacob/ws/ros/latest/src/ros2/rosidl_typesupport/rosidl_typesupport_cpp/src/type_support_dispatch.hpp:111, at /home/jacob/ws/ros/latest/src/ros2/rcl/rcl/src/rcl/publisher.c:114

Based on the error message, it doesn't look like Connext is happy with the default deadline value we're providing.

Foxy Support

Hello. Should the package work on ROS2 Foxy? When I try to manually build it I get some CMake related errors, and I don't see any foxy related branch.

Dynamically configure service bridges from YAML

Follow up to #10.

We can now bridge services, but it requires manually configuration due to needed typesupport information at compile-time. In order to support bridging services dynamically, we need better support at the RMW layer for generic services.

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.