Giter VIP home page Giter VIP logo

urdf2webots's Introduction

urdf2webots

Test Status PyPI version

This tool converts URDF files into Webots PROTO files or into Webots Robot node strings. Python 3.5 or higher is required.

Install

From pip

pip install urdf2webots

On macOS, export the pip binary path to the PATH: export PATH="/Users/$USER/Library/Python/3.7/bin:$PATH"

From Sources

git clone --recurse-submodules https://github.com/cyberbotics/urdf2webots.git
pip install --upgrade --editable urdf2webots

Usage

From pip

python -m urdf2webots.importer --input=someRobot.urdf [--output=outputFile] [--normal] [--box-collision] [--tool-slot=linkName] [--help]

Arguments

The script accepts the following arguments:

  • -h, --help: Show the help message and exit.
  • --input=INPUT: Specifies the URDF file to convert.
  • --output=OUTPUT: If set, specifies the path and, if ending in ".proto", name of the resulting PROTO file. The filename minus the .proto extension will be the robot name (for PROTO conversion only).
  • --robot-name: Specify the name of the robot and generate a Robot node string instead of a PROTO file (has to be unique).
  • --normal: If set, the normals are exported if present in the URDF definition.
  • --box-collision: If set, the bounding objects are approximated using boxes.
  • --tool-slot=LinkName: Specify the link that you want to add a tool slot to (exact link name from URDF, for PROTO conversion only).
  • --translation="0 0 0": Set the translation field of the PROTO file or Webots Robot node string.
  • --rotation="0 0 1 0": Set the rotation field of the PROTO file or Webots Robot node string.
  • --init-pos=JointPositions: Set the initial positions of your robot joints. Example: --init-pos="[1.2, 0.5, -1.5]" would set the first 3 joints of your robot to the specified values, and leave the rest with their default value.
  • --link-to-def: Creates a DEF with the link name for each solid to be able to access it using getFromProtoDef(defName) (for PROTO conversion only).
  • --joint-to-def: Creates a DEF with the joint name for each joint to be able to access it using getFromProtoDef(defName) (for PROTO conversion only).
  • --relative-path-prefix: If --input is not set, the relative paths in your URDF file sent through stdin will use this prefix. For example: filename="head.obj" with --relative-path-prefix="/home/user/myRobot/" will become filename="/home/user/myRobot/head.obj".

In case the --input option is missing, the script will read the URDF content from stdin. In that case, you can pipe the content of your URDF file into the script: cat my_robot.urdf | urdf2proto.py. Relative paths present in your URDF file will be treated relatively to the current directory from which the script is called unless --relative-path-prefix is set.

Previously the --static-base argument was supported in order to set the base link to be static (disabled physics). It has been removed as there is a better way to do it by adding the following to your URDF file (assuming base_link is the root link of your robot):

<link name="world" />
<joint name="world_joint" type="fixed">
   <parent link="world" />
   <child link="base_link" />
</joint>

In your Python Code

Arguments

The command line arguments available from the terminal are also available from the Python interface, but some have different names:

Terminal Python
--input input
--output output
--robot-name robotName
--normal normal
--box-collision boxCollision
--tool-slot toolSlot
--translation initTranslation
--rotation initRotation
--init-pos initPos
--link-to-def linkToDef
--joint-to-def jointToDef
--relative-path-prefix relativePathPrefix

In Python, you can convert a URDF file by passing its path as an argument to the convertUrdfFile() function or directly by passing its content as an argument to the convertUrdfContent() function.

Convert into Webots PROTO files

from urdf2webots.importer import convertUrdfFile
convertUrdfFile(input = 'MY_PATH/MY_URDF.urdf')

or

import pathlib
from urdf2webots.importer import convertUrdfContent
robot_description = pathlib.Path('MY_PATH/MY_URDF.urdf').read_text()
convertUrdfContent(input = robot_description)

Convert into Webots Robot node strings

from urdf2webots.importer import convertUrdfFile
convertUrdfFile(input = 'MY_PATH/MY_URDF.urdf', robotName="myRobot")

or

import pathlib
from urdf2webots.importer import convertUrdfContent
robot_description = pathlib.Path('MY_PATH/MY_URDF.urdf').read_text()
convertUrdfContent(input = robot_description, robotName="myRobot")

In-Depth Tutorial

Check out this tutorial for a more in-depth, step by step instruction, on how to:

  • Generate a URDF file from a ROS repository.
  • Convert your URDF file to a Webots PROTO file.
  • Load your converted model into Webots and make final adjustments.
  • Convert your URDF file to a Webots Robot string and import it.

Notes

This tool was tested using Webots R2022b on Ubuntu22.04. You can find the sources of these URDF files here:

Acknowledgements

rosin_logo

Supported by ROSIN - ROS-Industrial Quality-Assured Robot Software Components. More information: rosin-project.eu

eu_flag

This project has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement no. 732287.


opendr_logo

Supported by OpenDR - Open Deep Learning Toolkit for Robotics. More information: opendr.eu

eu_flag

This project has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement no. 871449.

urdf2webots's People

Contributors

ad-daniel avatar benjaminhug8 avatar brettle avatar cottsay avatar davidmansolino avatar fabienrohrer avatar frogguaguagua avatar giessen avatar h3ndrk avatar jgueldenstein avatar jgvictores avatar lukicdarkoo avatar mael25 avatar manuelz avatar michou214 avatar omichel avatar schnaubelt avatar simon-steinmann avatar stefaniapedrazzi avatar tahir1069 avatar tpjnorton avatar vidicon avatar wasabifan avatar ygoumaz avatar

Stargazers

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

Watchers

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

urdf2webots's Issues

TypeError: not enough arguments for format string

I am trying to convert a URDF file using the command found [here]:(https://github.com/cyberbotics/urdf2webots/blob/master/docs/tutorial.md)
python -m urdf2webots.importer --input=model.urdf --box-collision --multi-file --static-base --tool-slot=tool0 --rotation="1 0 0 -1.5708"
My urdf file was converted from a xacro file using ros-noetic-desktop (Winows 10, Python 3.8.10).
rosrun xacro xacro vector.xacro > vector_generated.urdf

The error is as follow:

(AnkiProject) C:\Users\User\Downloads\anki_description\urdf>python -m urdf2webots.importer --input=vector_generated.urdf --box-collision --multi-file --static-base --tool-slot=tool0 --rotation="1 0 0 -1.5708"
Robot name: vector
Parsing Mesh: C:\Users\User\Downloads/anki_description/meshes/vector_body.dae
Parsing Mesh: C:\Users\User\Downloads/anki_description/meshes/vector_head.dae
Parsing Mesh: C:\Users\User\Downloads/anki_description/meshes/vector_lift.dae
Parsing Mesh: C:\Users\User\Downloads/anki_description/meshes/cozmo_belt.dae
Parsing Mesh: C:\Users\User\Downloads/anki_description/meshes/cozmo_belt.dae
Root link: base_link
Unsupported "R8G8B8" image format, using "R8G8B8A8" instead.
There are 17 links, 16 joints and 7 sensors
Create meshFile: Vector_vector_body_0Mesh.proto
Create meshFile: Vector_vector_body_1Mesh.proto
Create meshFile: Vector_vector_body_2Mesh.proto
Create meshFile: Vector_vector_head_0Mesh.proto
Create meshFile: Vector_vector_head_1Mesh.proto
Create meshFile: Vector_vector_head_2Mesh.proto
Traceback (most recent call last):
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\site-packages\urdf2webots\importer.py", line 221, in <module>
    convert2urdf(options.inFile, options.outFile, options.normal, options.boxCollision, options.disableMeshOptimization,
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\site-packages\urdf2webots\importer.py", line 184, in convert2urdf
    urdf2webots.writeProto.URDFLink(protoFile, rootLink, 1, parentList, childList, linkList, jointList,
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\site-packages\urdf2webots\writeProto.py", line 131, in URDFLink
    URDFJoint(proto, joint, level + 2, parentList, childList,
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\site-packages\urdf2webots\writeProto.py", line 621, in URDFJoint
    URDFLink(proto, childLink, level + 1, parentList, childList,
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\site-packages\urdf2webots\writeProto.py", line 131, in URDFLink
    URDFJoint(proto, joint, level + 2, parentList, childList,
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\site-packages\urdf2webots\writeProto.py", line 590, in URDFJoint
    URDFLink(proto, childLink, level, parentList, childList,
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\site-packages\urdf2webots\writeProto.py", line 124, in URDFLink
    sensor.export(proto, level + 2)
  File "D:\STUDIES\Anaconda\envs\AnkiProject\lib\site-packages\urdf2webots\parserURDF.py", line 271, in export
    file.write(indentationLevel * indent + '  lookupTable [-1 -1 %lf, 1 1 %lf]\n' %
TypeError: not enough arguments for format string

Fixed joints seem to be ignored during conversion

Hi all,

I was using this tool with a couple different robots (franka emika panda and ur3e+robotiq_85) and it seems that the presence of fixed joints seem to be ignored. That is, when opened in Webots, any part of the robot after that fixed joint disconnects and falls due to gravity. As a test, I converted those joints to revolute ones, making them essentially fixed through the limits, and this seemed to fix the issue. I haven't fully tested the behavior of the robots with a controller, but will be doing so soon.
Attached is the panda urdf file that had the issues.

panda.txt

Bounding Box generation -> nested Transform

When a Link in an URDF file has translation or orientation, a Transform is used. However, if we enable box-collision, it created another transform. Webots doesnt allow nested Transforms for BoundingObjects
image
image

Tutorial shows that mesh linking is not working properly

In this tutorial we can use kuka arm and convert it to PROTO.

Since the updates of the mesh linking (version 1.0.11) it seems to not work properly (cannot see the base as it is encoded in indexed face set, each part is aligned with Y instead of Z and the texture is only a gray color).

See PR #136.

Exporter issue with stl files

The exporter seems to triangulate the mesh, and sometimes it flips face normal (see picture).
This only happens with stl not with dae.
Also, the dae is smoothed (left most mesh in the picture) in contrary to the stl.
image

I've check the normals in blender, they're ok.
Here is the command I used:

python -m urdf2webots.importer --input=robot.urdf --output=robot.proto --box-collision --disable-mesh-optimization

The option `--box-collision` of the convertor seems to work badly when convert a stl file

I have a robot's urdf file, and the visual of the robot uses the stl file. I have converted it into webots using this tool, but when I check the model, I find that the inertia of the solid is not set. So I read the documents of the webots, it said that when give the boundingObject of the solid, the inertia will calculate automatically. So I use the tool again to re-generate the proto file to get a box like collision shape, but the option seems to work badly.
For example:
the shape of solid Body is :(Mass of it is 11kg, the shape is complex)

                        # Shape {
                        #   appearance PBRAppearance {
                        #     baseColor 0.5 0.5 0.5
                        #     transparency 0
                        #     roughness 1
                        #     metalness 0
                        #     emissiveColor 0 0 0
                        #   }
                        #   geometry IndexedFaceSet {
                        #     coord Coordinate {
                        #       point [
                        #         ...
                        #     ]
                        #       coordIndex[
                        #         ...
                        #     ]
                        #     creaseAngle 1
                        #   }
                        # }

the results of the conversion:

                      boundingObject Sphere {
                        radius 0.005
                      }

So, Should I specify the inertia of the robot's rods directly in Numbers? But how do I make sure that I'm assigning the right inertia? Do webots have visual options like Gazebo to see the shape of the inertia?

Improvement of Duplicated Vertices Removal

For a better performance, the algorithm removing the duplicated vertices in a mesh should be improved:
https://github.com/omichel/urdf2webots/blob/c4ad004eccbd5bf97f3c6b1d31511d0f029e6df2/parserURDF.py#L384
Instead of parsing and removing the duplicated meshes at the same time, this should be done in 3 passes:

  1. Parse the file and add all the vertices.
  2. Loop over all the vertices, check for duplicated vertices and stor the index in a hash table.
  3. Loop the hash table to remove the actual duplicated vertices and update the index accordingly (replace index of removed vertices and shifting of the next indices).

How to deal with controllers and sensors

Hi,

We're totally new to webots (we have been using gazebo so far) and we were wondering how to specify sensors and other plugins, e.g. controllers in the urdf. A lidar sensor in URDF (for gazebo) would be something like:

<gazebo reference="front_scan">
    <sensor name="front_scan" type="gpu_ray">
      <update_rate>34</update_rate>
      <pose>0 0 0 0 0 0</pose>
      <visualize>false</visualize>
      <ray>
        <scan>
          <horizontal>
            <samples>1072</samples>
            <resolution>1</resolution>
            <min_angle>-1.5533430342749535</min_angle>
            <max_angle>1.5533430342749535</max_angle>
          </horizontal>
        </scan>
        <range>
          <min>0.08</min>
          <max>30.0</max>
          <resolution>0.01</resolution>
        </range>
        <noise>
          <type>gaussian</type>
          <mean>0.0</mean>
          <stddev>0.001</stddev>
        </noise>
      </ray>
      <plugin filename="libgazebo_ros_gpu_laser.so" name="gazebo_ros_front_scan_controller">
        <topicName>front_scan</topicName>
        <frameName>front_scan</frameName>
      </plugin>
    </sensor>
  </gazebo>

How does this work for webots. We have tried the exporter and all links get exported (including geometry) but how to specificy sensors / actuators / plugins? We would like to maintain one robot description (like we have now).

Thanks!

Center of Mass not exported

Hi,
I have tried the converter with a simple differential drive robot dd3.urdf and it seems it doesn't add the center of mass giving this output

    INFO: dd3 (PROTO) > Solid > Physics: You must also specify the 'centerOfMass' when specifying the 'inertiaMatrix'
    WARNING: dd3 (PROTO) > Solid > Physics: 'centerOfmass' must also be specified when using an inertia matrix.

I tried adding an explicit origin tag in the URDF but that didn't help.

Might be off-topic: Adding the centerOfMass manually to each Solid, when I try to visualise it in Webots it shows this error which I am not sure it is related to the above

 INFO: DEF dd3 dd3 (PROTO): A Solid with a non-NULL Physics node must be chosen.

Thanks!

Joint axes not correctly exported

Some hingejoint axis doesn't correspond to the URDF after converting using urdf2webots.
For example, in Rviz (using roslaunch urdf_tutorial display.launch model:=robot.urdf.xacro) when joint_2 is increased, and doing the same in Webots, the axis of rotation is sometimes different (joint does not rotate in the same direction or joint does not rotate in the same axis).

See the following screenshot:
image

Camera orientation

In a URDF the camera optical frame is usually specified as per https://www.ros.org/reps/rep-0103.html#suffix-frames

Webots uses a different standard described here https://www.cyberbotics.com/doc/reference/viewpoint

Therefore the camera is looking in the wrong direction and it is upside down as seen here
Screenshot from 2021-01-15 11-42-42

The problem to the solution can be to introduce an additional Transform in the export function of the Camera class

def export(self, file, indentationLevel):

such that the camera is rotated in relation the the camera optical frame.

Solid {
  translation 0.043200 0.080000 -0.023500
  rotation 0.707105 -0.000001 0.707108 3.141591
  children [
    Transform {
    rotation 1.0 0.0 0.0 3.141591
    children [
      Camera {
        name "camera"
        fieldOfView 0.570000
        width 620
        height 480
        near 0.08
      }
      ]
    }
  ]
  name "camera_optical_frame"
}

After this the camera is rotated correctly:
Screenshot from 2021-01-15 11-53-29

I can provide a PR if you are interested.

Feature request: custom proto code in urdf

For our application we need support for closed-loop kinematics.
Unfortunately the urdf format does not support it.

I could modify the generated .proto file to contain the SolidReference required to do so. But this would mean the proto starts deviating from the urdf and cannot be re-generated anymore.

Would it be possible / wise to allow for custom .proto entries in the urdf model? Kind of similar how you can add sdf elements for gazebo.

URDF2Webots: Xacro Import: Parser.py gives an error

I'm having some trouble importing and converting a xacro file.
Does URDF2Webots rely on a different version of python?

Using Ubuntu 20.04, Webots R2021b, ROS2 Foxy.

We have a previous project in Gazebo with some mesh files that we are trying to port into Webots, but I'm having trouble with the import. Webots, Gazebo, ROS 2 are all working.

Screenshot from 2021-11-05 19-18-50

Missing 'name' field

Currently, the 'name' field is not open, this causes issues because several robots use the 'base_link' as root name which causes name clashes.

mobile manipulators and aerial manipulators, problems with the generation of wheel collision forms

When generating the system in solidworks and exporting using solid2urdf it works correctly and in gazebo it does not give problems, but we want to use this robot in webots because of the advantages that this simulator has, but when using urdf2webots the forms of collision that it generates do not allow the wheels to rotate correctly, a possible solution we did is to modify the .proto by adding collision cylinders on the wheels.
The original files generated by urdf2webots are attached in urdf folder
rover.zip

Robot Falling down when simulation starts.

When i start the simulation,the robot falls down. Its probably the transformation. I fixed it in the world but still it falls out. What to do? I want to use to communicate with my robot to test the controller i developed with Gazebo.

How to fix this issue.

Thank You

Empty URDF links should have no physics node

Currently, empty links in a urdf file such as this:
<link name="base"/>
get converted into a node like this:

Solid {
        translation 0.000000 0.000000 0.000000
        rotation 0.000000 1.000000 0.000000 0.000000
        name "base"
        physics Physics {
          density -1
          mass 1.000000
          centerOfMass [ 0.000000 0.000000 0.000000 ]
        }
      }

Webots then complains that it has no inertia matrix or bounding object. Empty links should be massless and have no physics node. The importer should be adjusted accordingly

Question: why not introduce a <webots> tag?

When diving a little bit more into webots and this urdf2webots parser I started wondering the following:

Why not introduce a <webots> xml tag instead of parsing the <gazebo> tags? Webots is a different simulator and also your sensor and actuator components are differently reflected in your resulting file (.proto file). Wouldn't it be easier (and more complete) to introduce a custom <webots> tag that describes the webots specific information regarding actuators and sensors?

Looking forward to your thoughts.

Unsupported mesh format for collision: ".STL"

I'm trying to convert the kinova GEN3 arm to .proto, using the urdf2webots tool. Doing so throws these errors:

python -m urdf2webots.importer --input=Kinova_Gen3_6DOF.urdf --box-collision
Robot name: GEN3-6DOF_NO-VISION_URDF_ARM_V01
Directory "GEN3-6DOFNO-VISIONURDFARMV01_textures" already exists!
Parsing Mesh: /home/simon/Documents/gitlab/sim2real_baselines_webots/simulations/ros_workspace/src/ros_kortex/kortex_description/arms/gen3/6dof/meshes/base_link.STL
Unsupported mesh format for collision: ".STL"
Parsing Mesh: /home/simon/Documents/gitlab/sim2real_baselines_webots/simulations/ros_workspace/src/ros_kortex/kortex_description/arms/gen3/6dof/meshes/shoulder_link.STL
Unsupported mesh format for collision: ".STL"
Parsing Mesh: /home/simon/Documents/gitlab/sim2real_baselines_webots/simulations/ros_workspace/src/ros_kortex/kortex_description/arms/gen3/6dof/meshes/bicep_link.STL
Unsupported mesh format for collision: ".STL"
Parsing Mesh: /home/simon/Documents/gitlab/sim2real_baselines_webots/simulations/ros_workspace/src/ros_kortex/kortex_description/arms/gen3/6dof/meshes/forearm_link.STL
Unsupported mesh format for collision: ".STL"
Parsing Mesh: /home/simon/Documents/gitlab/sim2real_baselines_webots/simulations/ros_workspace/src/ros_kortex/kortex_description/arms/gen3/6dof/meshes/spherical_wrist_1_link.STL
Unsupported mesh format for collision: ".STL"
Parsing Mesh: /home/simon/Documents/gitlab/sim2real_baselines_webots/simulations/ros_workspace/src/ros_kortex/kortex_description/arms/gen3/6dof/meshes/spherical_wrist_2_link.STL
Unsupported mesh format for collision: ".STL"
Parsing Mesh: /home/simon/Documents/gitlab/sim2real_baselines_webots/simulations/ros_workspace/src/ros_kortex/kortex_description/arms/gen3/6dof/meshes/bracelet_no_vision_link.STL
Unsupported mesh format for collision: ".STL"
Root link: base_link
There are 8 links, 7 joints and 0 sensors

Steps to reproduce:

  1. install urdf2webots:
    pip install urdf2webots

  2. build kinova_kortex as per instructions here: https://github.com/Kinovarobotics/ros_kortex
    (I pasted commands below for convenience)

    sudo apt install python3 python3-pip
    sudo python3 -m pip install conan
    conan config set general.revisions_enabled=1
    conan profile new default --detect > /dev/null
    conan profile update settings.compiler.libcxx=libstdc++11 default
    mkdir -p catkin_workspace/src
    cd catkin_workspace/src
    git clone https://github.com/Kinovarobotics/ros_kortex.git
    cd ../
    rosdep install --from-paths src --ignore-src -y

then build and source devel/setup.bash

  1. place the attached urdf file into a directory and run this command in the terminal:
    python -m urdf2webots.importer --input=Kinova_Gen3_6DOF.urdf --box-collision

Kinova_Gen3_6DOF.zip

Need extensionSlot in generated proto file

I'm trying to recreate the webots_ros2_turtlebot example with a custom robot and use it with the new plugin system. I was facing some trouble with an error message like this:

[driver-3] Warning: "inertial_unit" device not found.
[driver-3] terminate called after throwing an instance of 'std::runtime_error'
[driver-3]   what():  Cannot find InertialUnit with name inertial_unit

I found out that my generated PROTO file, based on an URDF, is missing something like this for my world's extensionSlot to work:

field MFNode     extensionSlot   [ ]

A line like this should probably go here:

proto.write('  field  MFNode      extensionSlot   []    ' + spaces + '# Extends the robot with new nodes in the extension slot.\n')

But something like this seems to be needed as well (based on this):

    Transform {
        rotation 0.5773503 -0.5773503 -0.5773503 2.0943951
        translation -0.03 0 0.153
        children IS extensionSlot
      }

But I'm not sure how to add that in a generic way.

NameError: global name 'PackageNotFoundError' is not defined

System information

  • Ubuntu 20.04.4 LTS
  • Python 2.7.18
  • Python 3.8.10

Installation of urdf2webots

$ curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1863k  100 1863k    0     0  9411k      0 --:--:-- --:--:-- --:--:-- 9411k
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
Defaulting to user installation because normal site-packages is not writeable
Collecting pip<21.0
  Downloading pip-20.3.4-py2.py3-none-any.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 11.3 MB/s 
Collecting setuptools<45
  Downloading setuptools-44.1.1-py2.py3-none-any.whl (583 kB)
     |████████████████████████████████| 583 kB 11.0 MB/s 
Collecting wheel
  Downloading wheel-0.37.1-py2.py3-none-any.whl (35 kB)
Installing collected packages: pip, setuptools, wheel
  WARNING: The scripts pip, pip2 and pip2.7 are installed in '/home/drakeprovost/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The scripts easy_install and easy_install-2.7 are installed in '/home/drakeprovost/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The script wheel is installed in '/home/drakeprovost/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
ERROR: pip's legacy dependency resolver does not consider dependency conflicts when selecting packages. This behaviour is the source of the following dependency conflicts.
launch-ros 0.11.6 requires pyyaml, which is not installed.
Successfully installed pip-20.3.4 setuptools-44.1.1 wheel-0.37.1
$ python -m pip install urdf2webots
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
Defaulting to user installation because normal site-packages is not writeable
Collecting urdf2webots
  Downloading urdf2webots-1.0.16.tar.gz (30 kB)
Collecting pycollada>=0.6
  Using cached pycollada-0.7.2.tar.gz (107 kB)
Collecting Pillow
  Downloading Pillow-6.2.2-cp27-cp27mu-manylinux1_x86_64.whl (2.1 MB)
     |████████████████████████████████| 2.1 MB 11.0 MB/s 
Collecting numpy
  Downloading numpy-1.16.6-cp27-cp27mu-manylinux1_x86_64.whl (17.0 MB)
     |████████████████████████████████| 17.0 MB 10.9 MB/s 
Collecting rospkg
  Downloading rospkg-1.3.0.tar.gz (41 kB)
     |████████████████████████████████| 41 kB 205 kB/s 
Collecting python-dateutil>=2.2
  Downloading python_dateutil-2.8.2-py2.py3-none-any.whl (247 kB)
     |████████████████████████████████| 247 kB 10.8 MB/s 
Collecting catkin_pkg
  Downloading catkin_pkg-0.4.24.tar.gz (61 kB)
     |████████████████████████████████| 61 kB 7.9 MB/s 
Collecting PyYAML
  Downloading PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl (574 kB)
     |████████████████████████████████| 574 kB 10.8 MB/s 
Collecting distro
  Downloading distro-1.6.0-py2.py3-none-any.whl (19 kB)
Collecting six>=1.5
  Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Collecting docutils
  Downloading docutils-0.18.1-py2.py3-none-any.whl (570 kB)
     |████████████████████████████████| 570 kB 10.8 MB/s 
Collecting pyparsing
  Downloading pyparsing-2.4.7-py2.py3-none-any.whl (67 kB)
     |████████████████████████████████| 67 kB 7.7 MB/s 
Building wheels for collected packages: urdf2webots, pycollada, rospkg, catkin-pkg
  Building wheel for urdf2webots (setup.py) ... done
  Created wheel for urdf2webots: filename=urdf2webots-1.0.16-py2-none-any.whl size=29277 sha256=d8b082c761b2ee8c25eb3f31f0caee24c18753997950256edbafa8a62e0f0a1a
  Stored in directory: /home/drakeprovost/.cache/pip/wheels/93/58/4d/9d09a6d750bd527560cfd4aee5688d64aab36152450d7ec329
  Building wheel for pycollada (setup.py) ... done
  Created wheel for pycollada: filename=pycollada-0.7.2-py2-none-any.whl size=127010 sha256=b87b874f71c08e61c3e69d0d8d485308ce378900e2050e220cc0dd5367c9a0bd
  Stored in directory: /home/drakeprovost/.cache/pip/wheels/45/ae/8a/01f8ebbc2b52f5ab297fd932ddb9228b84e80a0bc7c851efc3
  Building wheel for rospkg (setup.py) ... done
  Created wheel for rospkg: filename=rospkg-1.3.0-py2-none-any.whl size=35571 sha256=1e5c51aed75d720d3c07ad45d3aad5e7fd543d19568fcb971d11e4c64bbb84ee
  Stored in directory: /home/drakeprovost/.cache/pip/wheels/5f/a3/72/d6457a71e4028d86a4c4a7edeef9de4cd275b4133374ebed3b
  Building wheel for catkin-pkg (setup.py) ... done
  Created wheel for catkin-pkg: filename=catkin_pkg-0.4.24-py2-none-any.whl size=74982 sha256=3ba7f5dfa10664fe0297d70f5b240411cb060ae97437fce128bb378c00627057
  Stored in directory: /home/drakeprovost/.cache/pip/wheels/53/1e/dc/ab9bc967b639a0c879ce348af6a8cede07fee48b666b2b8add
Successfully built urdf2webots pycollada rospkg catkin-pkg
Installing collected packages: six, python-dateutil, numpy, pycollada, Pillow, docutils, pyparsing, catkin-pkg, PyYAML, distro, rospkg, urdf2webots
  WARNING: The scripts f2py, f2py2 and f2py2.7 are installed in '/home/drakeprovost/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The scripts catkin_create_pkg, catkin_find_pkg, catkin_generate_changelog, catkin_package_version, catkin_prepare_release, catkin_tag_changelog and catkin_test_changelog are installed in '/home/drakeprovost/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The script distro is installed in '/home/drakeprovost/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  WARNING: The script rosversion is installed in '/home/drakeprovost/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed Pillow-6.2.2 PyYAML-5.4.1 catkin-pkg-0.4.24 distro-1.6.0 docutils-0.18.1 numpy-1.16.6 pycollada-0.7.2 pyparsing-2.4.7 python-dateutil-2.8.2 rospkg-1.3.0 six-1.16.0 urdf2webots-1.0.16

Expected Output

I used the command python -m urdf2webots.importer --input=Rover_2022.urdf --output=Rover_2022.proto, which should've generated the proto file.

Broken Output

$ python -m urdf2webots.importer --input=Rover_2022.urdf --output=Rover_2022.proto
Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/drakeprovost/.local/lib/python2.7/site-packages/urdf2webots/importer.py", line 334, in <module>
    options.enableMultiFile, options.toolSlot, options.initTranslation, options.initRotation, options.initPos, options.linkToDef, options.jointToDef, options.relativePathPrefix)
  File "/home/drakeprovost/.local/lib/python2.7/site-packages/urdf2webots/importer.py", line 89, in convertUrdfFile
    initPos, linkToDef, jointToDef, relativePathPrefix)
  File "/home/drakeprovost/.local/lib/python2.7/site-packages/urdf2webots/importer.py", line 174, in convertUrdfContent
    except PackageNotFoundError:
NameError: global name 'PackageNotFoundError' is not defined

Converter prunes URDF branches of sensors

Unfortunately, I found out about this problem only recently. But latest version of the converter is pruning important (static/fixed) links from the URDF where sensors are attached. In this specific case, the optical frames of cameras are truncated.

Current behavior:

Camera frame is supposed to be the optical link that is truncated by the converter. I suspect that Webot has a fallback to attach them to the root link as seen in the following screenshot.

Screenshot from 2022-06-27 18-02-35

Expected behavior:

Cheated by changing the URDF to set the camera frame to the last non-truncated link.

Screenshot from 2022-06-27 18-01-06

Unable to able porto file into webots simulation

Hello,

I have converted my urdf into porto file but unable to import it.

  1. In my project, my porto file is available in portos
  2. Launching simulation with emoty.wbt
  3. When i add with porto nodes, i am unable to see the file.

I do not what is missing ?

Sensors are placed in base frame instead of respective frame

Sensors (camera and IMU) are placed in the base frame instead of their respective frame.

This is the sensor description in our URDF:

<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="wolfgang">
[...]
  <!-- camera sensor -->
  <gazebo reference="camera">
      <sensor name='camera' type='camera'>
        <pose>-0.050000 -0.010000 0.000000 -1.5708 0.000000 -3.141592</pose>
        <camera name='__default__'>
          <horizontal_fov>0.57</horizontal_fov>
          <image>
            <width>620</width>
            <height>480</height>
          </image>
          <clip>
            <near>0.001000</near>
            <far>100.000000</far>
          </clip>
        </camera>
        <always_on>1</always_on>
        <update_rate>30.000000</update_rate>
        <visualize>1</visualize>
        <plugin name="camera_controller" filename="libgazebo_ros_camera.so">
          <alwaysOn>true</alwaysOn>
          <updateRate>30</updateRate>
          <cameraName>camera</cameraName>
          <imageTopicName>camera/image_proc</imageTopicName>
          <cameraInfoTopicName>camera_info</cameraInfoTopicName>
          <frameName>camera_optical_frame</frameName>
          <hackBaseline>0.07</hackBaseline>
          <distortionK1>0.0</distortionK1>
          <distortionK2>0.0</distortionK2>
          <distortionK3>0.0</distortionK3>
          <distortionT1>0.0</distortionT1>
          <distortionT2>0.0</distortionT2>
        </plugin>
      </sensor>
  </gazebo>
  [...]
  <!-- IMU sensor -->
  <gazebo reference="imu_frame">
      <gravity>true</gravity>
      <sensor name="imu_sensor" type="imu">
          <always_on>true</always_on>
          <update_rate>100</update_rate>
          <visualize>true</visualize>
          <topic>__default_topic__</topic>
          <plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
              <topicName>imu</topicName>
              <bodyName>imu_frame</bodyName>
              <updateRateHZ>100.0</updateRateHZ>
              <gaussianNoise>0.0</gaussianNoise>
              <xyzOffset>0 0 0</xyzOffset>
              <rpyOffset>0 0 0</rpyOffset>
              <frameName>imu_frame</frameName>
          </plugin>
          <pose>0 0 0 0 0 0</pose>
      </sensor>
  </gazebo>
[...]
</robot>

I believe the issue to be in

def parseGazeboElement(element, parentLink, linkList):

Gazebo allows to use the reference attribute but webots2urdf ignores it and expects gazebo and therefore also the sensor elements to be in the link they belong to.

I can provide a PR to fix this if you are interested.

Add option to refer to mesh files instead of deep copying meshes into proto files

Hi,

Currently the urdf exporter deep copies all meshes from any sources. This potentially bloats the proto files to multiple hundreds of megabytes, makes them not well editable anymore.

It would be very convenient to have an option that the exporter refers to files instead of deep copying their content. I've already implemented a kind of prototype for my case. I would appreciate seeing such a feature officially supported in the future. Feel free to use my code as a starting point: astumpf@4a9da68

Best regards

Error during conversion

I am trying to convert urdf of my robot into webots but its showing following error.

Root link: panda_virtual_link_0
Traceback (most recent call last):
File "urdf2webots.py", line 138, in
parserURDF.parseGazeboElement(child, rootLink.name, linkList)
File "/home/sunny/development/catkinws/src/urdf2webots/parserURDF.py", line 801, in parseGazeboElement
print('Unsupported "%lf" image format, using "R8G8B8A8" instead.' % imageElement.getElementsByTagName('format')[0].firstChild.nodeValue)
TypeError: float argument required, not unicode

Can you please help me to convert it.

Thank You

Treat collada.material.Effect when returns collada.material.Map rather than Tuple

Hello!

I've been using urdf2webots to port some humanoid robots to Webots (e.g. https://github.com/roboticslab-uc3m/teo-webots-models lacks textures and dynamics but serves its purpose). While porting PAL Robotics REEM-C robot, I ran into TypeError: 'Map' object does not support indexing upon passing through visual.material.specular = colorVector2Instance(data.material.effect.specular). Here are the robot model repositories:

It turns out a Python tupleis expected; however, https://pycollada.readthedocs.io/en/latest/reference/generated/collada.material.Effect.html#collada.material.Effect as documented can alternatively return an instance of collada.material.Map, which is the case for this robot. The shameless (and textureless) hack at https://github.com/cyberbotics/urdf2webots/blob/master/urdf2webots/parserURDF.py#L553 (perma) was the following:

-                    if data.material.effect.specular:
+                    if data.material.effect.specular and isinstance(data.material.effect.specular, tuple):

I understand the expected behavior would be to treat the different situations where https://pycollada.readthedocs.io/en/latest/reference/generated/collada.material.Effect.html#collada.material.Effect returns a collada.material.Map (which is not restricted to specular), and/or at least prevent the TypeError. Thank you!

Base link is missing physics element that breaks Gyro node use

Since 2d62081 a major change was applied that prevents to attach a physics node to the root element (base). I've also noticed that the new version does generate a lot less links, I guess there is some kind of simplifications regarding static links involved. However, this breaks any current usage with Gyro sensor (parsed from IMU elements from URDF). Now all Gyro nodes are complaining for a missing physics-enabled parent node.

Diffing the previously generated proto file with the new file reveals following change:

Screenshot from 2022-03-28 19-18-21

Readding these lines, fixes the Gyro problem. Therefore, I'm wondering how to fix that issue in the convertor.

sensorElement always refers to the first element of a list

I think this line shouldn't exist because in the previous line, where you are looping, you already have a sensorElement.

I have 4 <sensor> tags with different types of cameras and I'm getting 4 cameras of the same first type.

for sensorElement in element.getElementsByTagName('sensor'):
    sensorElement = element.getElementsByTagName('sensor')[0]

Empty textures folder problem with URDF to PROTO conversion

Hello,
I created a xacro file which combines UR5e + Robotiq 2f85 gripper and automatically generated the URDF from that.
I can display and move the robot and the gripper on RVIZ so the URDF file is okay.
When I'm trying to convert the model to a PROTO file to be able to use in Webots, I get the output ur5e_with_2f85.proto but the auto-generated textures folder is empty.
In my URDF file I am using ur5e and 2f85 descriptions from other ros packages in my workspace so my initial guess is that it could be a problem with relative paths. But the terminal output correctly displays the absoluth paths of the dae files that are being imported.

There are entries in the URDF such as:

<geometry>
   <mesh filename="package://ur_description/meshes/ur5e/visual/shoulder.dae"/>
 </geometry>

I do the conversion with:
python3 -m urdf2webots.importer --input=ur5e_with_2f85.urdf

And the output is:

Robot name: ur5e_with_2f85
Parsing Mesh: home/og/catkin_ws/src/universal_robot/ur_description/meshes/ur5e/visual/base.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/universal_robot/ur_description/meshes/ur5e/visual/shoulder.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/universal_robot/ur_description/meshes/ur5e/visual/upperarm.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/universal_robot/ur_description/meshes/ur5e/visual/forearm.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/universal_robot/ur_description/meshes/ur5e/visual/wrist1.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/universal_robot/ur_description/meshes/ur5e/visual/wrist2.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/universal_robot/ur_description/meshes/ur5e/visual/wrist3.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/visual/robotiq_arg2f_85_outer_knuckle.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/collision/robotiq_arg2f_85_outer_knuckle.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/visual/robotiq_arg2f_85_outer_finger.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/collision/robotiq_arg2f_85_outer_finger.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/visual/robotiq_arg2f_85_inner_finger.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/collision/robotiq_arg2f_85_inner_finger.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/visual/robotiq_arg2f_85_inner_knuckle.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/collision/robotiq_arg2f_85_inner_knuckle.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/visual/robotiq_arg2f_85_outer_knuckle.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/collision/robotiq_arg2f_85_outer_knuckle.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/visual/robotiq_arg2f_85_outer_finger.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/collision/robotiq_arg2f_85_outer_finger.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/visual/robotiq_arg2f_85_inner_finger.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/collision/robotiq_arg2f_85_inner_finger.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/visual/robotiq_arg2f_85_inner_knuckle.dae
Parsing Mesh: /home/og/syn/adapt/adapt_ros/src/robotiq/robotiq_2f_85_gripper_visualization/meshes/collision/robotiq_arg2f_85_inner_knuckle.dae
Root link: world
There are 19 links, 18 joints and 0 sensors

Thank you in advance for any kind of help!

Question: Update rate of sensor

In the sdf format an update_rate for sensors is defined, but unfortunately this field is not available in the parser right now.
This field would be useful to increase or decrease sensor updates of cameras, range finders, imus, etc. and therefore useful to improve upon simulation performance and match real robots better.
Is there a way how this can be implemented/passed to the webots ros controller?

How to reflect meshes loaded from files?

Robots are usually symmetrical and therefore many parts are identical but reflected. Using URDF it's common practice to just use the identical mesh multiple times and just reflect it by using negative scales, e.g. for mirroring along the x-z plane (sagittal) you would use the scaling vector [1 -1 1]. However, Webots forbids this type of mesh reflection using the Transform node (https://cyberbotics.com/doc/reference/transform).

Transform {
  translation 0.000000 0.000000 0.060000
  rotation 0.000000 0.000000 1.000000 0.000000
  scale 1.000000 -1.000000 1.000000
  children [
    Shape {
      appearance PBRAppearance {
        baseColor 0.500000 0.500000 0.500000
        transparency 0.000000
        roughness 1.000000
        metalness 0
        emissiveColor 0.000000 0.000000 0.000000
      }
      geometry DEF my_mesh Mesh {
        url "my_awesome_mesh.obj"
      }
    }
  ]
  }

Is there any way to reuse a single mesh file in case of reflections?

Feature request: generate separate .proto files for meshes

Currently the script generates one big .proto file. For a complex robot this is can make the .proto file very large. Large files are difficult to edit as there are quit unclear and the text editor becomes very slow.

In some example robots (kuka youbot) I have seen the robot been split into separate files. It would be very nice if the converter script would give you the option to generate a separate .proto files for the original mesh files.

Advantages:

  • easier editing of the model.
  • cleaner model files.
  • decrease single file size.
  • mesh files become reusable.
  • clearer version control.

Automatic Shape USE-DEF

We should add a new argument to create automatically USE-DEF in case the same mesh is used several times.

Feature Request: Add Fields (collision, static base etc.)

I converted several robotic arms, and there are a few things I always have to do manually:

  1. Adding these fields

  field SFBool     supervisor      FALSE             # Is `Robot.supervisor`.
  field SFBool     synchronization TRUE              # Is `Robot.synchronization`.
  field SFBool     selfCollision   TRUE              # Is `Robot.selfCollision`.
  field MFNode     toolSlot        []                # Extend the robot with new nodes at the end of the arm.
  field SFBool     staticBase      TRUE              # Defines if the robot base should ba pinned to the static environment.
  1. Adding the if statement to the Physics node of the base_link and implementing the Fields
  %{ if fields.staticBase.value == false then }%
   physics Physics {
     density -1
     mass 4
     centerOfMass [
       0 0 0
     ]
   }
   %{ end }%
   controller IS controller
   controllerArgs IS controllerArgs
   supervisor IS supervisor
   synchronization IS synchronization
   selfCollision IS selfCollision
 }
}
  1. Adding the ToolSlot Transform in the last link:
                                      endPoint Solid {
                                        translation 0 0 0.12
                                        children [
                                          Shape {
                                            appearance USE METAL_APPEARANCE
                                            geometry IndexedFaceSet {
                                              coord Coordinate {
                                                point [... ]
                                              }
                                              coordIndex [...   ]
                                              creaseAngle 0.6
                                            }
                                          }
                                          Transform {
                                            translation 0 0.12 0
                                            children IS toolSlot
                                           }

It would be very beneficial, if these things could be added automatically (especially 1. and 2.)

Converting the `realsense_ros_gazebo` URDF outputs almost empty PROTO

I tried to export a PROTO from the nilseuropa/realsense_ros_gazebo but it doesn't export any meshes.

I believe the problem is here:

# if root link has only one joint which type is fixed,
# it should not be part of the model (link between robot and static environment)

as d435_bottom_screw_frame and d435_link links are not exported. I believe if root link has only one joint which type is fixed, it should not be part of the model is a very strong assumption and we should better handle it.

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.