Setting up ROS in Windows through WSL2

Introduction

This post is a tutorial on how to set up a working ROS development environment within Windows (complete with GUI support) utilizing the new Windows Subsystem for Linux 2 (WSL2). I wrote a similar post to this previously describing how to do it for WSL1 and a lot of that info carries over here. If you want to learn about why I choose to use WSL instead of a Virtual Machine (VM) or dual-booting into Linux, you can read about that in the above post.

Before we get started I’d like to point out that my previous post on this topic for WSL1 has been a major hit. That blog post gets hundreds of views per week and I’m blown away by how many people have been helped by it. I want you all to know that I really appreciate all the feedback I get and that I actively check the comments on this blog and all emails I get about it (contact info) so don’t be shy and reach out with comments and questions!

NOTE #1: If you’d like to know how to set this up in Docker, I have another tutorial here that shows how to do that.

NOTE #2: You have to be running Windows 10 version 2004 (Build 19041) or higher for WSL2 to work.

WSL Installation

WSL2 is a complete reworking of WSL that shifts from what was essentially an emulation based approach to a virtualization based approach. WSL2 comes with a full Linux kernel and runs as a very lightweight VM on top of hypervisor. This gives tremendous improvements to performance over WSL1 specifically when it comes to boot times and I/O performance (we’re talking up to 20x speed improvements).

Installing and setting up WSL2 is pretty straightforward (you can see the full docs here). First, you need to enable the WSL optional feature in Windows so open up a PowerShell prompt as Administrator and run this command:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

If we were going to use WSL1 that is all we would have to do, but to use WSL2 there are a couple extra steps. You need to enable the Virtual Machine Platform optional feature by running the below command in PowerShell as Administrator:

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

You then need to restart your machine to finish the WSL install and the upgrade to WSL2.

After the restart, we want to make sure that WSL2 is our default WSL version so that any Linux distros installed from here on out will be WSL2 (though you can always upgrade or downgrade distros later on). To set WSL2 as the default, run the below command in a PowerShell prompt:

wsl --set-default-version 2

After running this command, you may see this message: WSL 2 requires an update to its kernel component. For information please visit https://aka.ms/wsl2kernel. If you do, go to the link in the message and update your Linux kernel by installing the MSI that you download from that site. Once the kernel is installed, run the above command again and verify that the message doesn’t appear.

If you already have a WSL1 installation, you can upgrade it to WSL2 using the below command and just replace <distribution name> with the name of the distro you want to upgrade:

wsl --list --verbose #list wsl distros
wsl --set-version <distribution name> 2 #change a distro to WSL2

If you don’t already have Ubuntu installed through WSL1, let’s go ahead and install it now! Head over to the Microsoft Store app and search for “linux”.

Click “Show all” to see all Linux distros

This will give you a bunch of options including Kali, Ubuntu, Debian, and others. For ROS we need Ubuntu installed and in this tutorial I will choose Ubuntu 18.04 LTS. Keep in mind that Ubuntu and ROS versions are paired with each other: e.g. 16.04/Kinetic and 18.04/Melodic. They don’t work interchangeably. So in this walkthrough I will install Ubuntu 18.04 and then later we’ll install ROS Melodic.

All that being said, simply click on your Ubuntu version of choice and then click install. This might take a bit depending on your internet speeds since the distribution is fairly large.

Now we can launch that app and it will take a bit the first time as it needs to run through the initialization of the OS (remember that we are installing a complete operating system here). However, every other boot of WSL will only take a couple of seconds.

Now you’re in! You have an (almost) fully-featured version of Ubuntu running within Windows with minimal resources being taken up and the ability to launch and kill it in a matter of seconds.

NOTE: Your WSL2 filesystem resides within your file explorer at \\wsl$\Ubuntu-18.04

Setting up GUI forwarding

There are many X-server applications that will allow for GUI forwarding from WSL2, but my favorite one is VcXsrv. Go here to download and install it.

Once you run the installer you can launch it from the Start menu in order to set it up. You can choose the defaults for the display settings and how to start clients. For the extra settings make sure to uncheck “Native opengl” and to check “Disable access control”. Right before you click “finish” you can select “Save configuration” so that you can simply double-click the config file to launch VcXsrv with these custom settings. This is a bit faster than clicking through every time.

Example of adjusted VcXsrv settings

Once you click “finish” you should see the VcXsrv icon down in your icon tray which means the server is running.

NOTE: Some people have said that they run into issues with OpenGL applications like Rviz. If you do, try setting the environment variable LIBGL_ALWAYS_INDIRECT=0 in your WSL2 terminal (you can just add export LIBGL_ALWAYS_INDIRECT=0 to the end of your .bashrc file).

Once that’s set up, we need to set the DISPLAY environment variable which tells WSL2 where to send the graphics for any application that needs a display to function. To do this, you’ll need to know the IP address for the Windows host machine. You can find this by going to Settings -> Network & Internet and looking under the properties of your current connection (it will probably be labeled as “IPv4 Address”). Then run this command and replace {your_ip_address} with your IP address:

echo 'export DISPLAY={your_ip_address}:0.0' >> ~/.bashrc

NOTE: If you’re running this on a laptop then your IP address will change as you move from network to network. Also, if you’re on a larger network (at a school campus or big company) you’re IP may change from time to time. Just keep in mind that you may need to update this IP address every once in a while.

Now source your edited .bashrc file:

source ~/.bashrc

Now everything should be setup for GUI apps to be sent on to Windows for rendering and display. If you want to test the setup, you can install some basic apps within Ubuntu with the below package:

sudo apt update
sudo apt install x11-apps

And then run:

xcalc

To run one of the apps. You can also install any of your favorite GUI apps or test it with ROS after we install that. Speaking of which…

ROS Installation

Now to install ROS. The ROS team has a great installation guide over here for the different ROS versions on different OSes but here we’re just going to do the steps for Ubuntu 18.04/ROS Melodic. Go here for more details.

First, make sure your version of Ubuntu has all the latest updates (all the commands below should be run from the shell within the Ubuntu app or from the same shell but in the Windows Terminal):

sudo apt update
sudo apt upgrade

Then we need to add the ROS package information to the sources list on our WSL system. To do this, run the below command:

sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'

Now we need to setup the keys for these package repositories:

sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

NOTE: If you get some errors with the above command try substituting hkp://pgp.mit.edu:80.

Now we need to update the local list of available packages with these newly added ROS ones:

sudo apt update

Now we’re (finally) ready to install ROS. There’s a few options to choose from:

  • desktop-full: This includes everything; rqt, rviz, simulators, navigation, perception, you name it.
  • desktop: This has most of the above but lacks the simulators, navigators, and perception.
  • ros-base: This is just the basics for getting up and running with ROS. No GUI tools and only what you need to package, build, and communicate over the ROS stack.

My recommendation is to go with desktop-full unless you are super short on storage. It’ll take a bit more time for the initial install and take up more disk space, but you’re guaranteed to have most of the tools you need for anything you’d like to do. However, with all of these you can simply add more tools as you need them. Simply run apt-cache search ros-melodic to find which ones are available.

Once you’ve chosen the ROS installation you want to get, run the below command and substitute in your choice. I’ll do desktop-full here:

sudo apt install ros-melodic-desktop-full

Depending on your network speed, this might take a while to install.

ROS needs to be sourced each time you open a bash shell and so we can add it to the ~/.bashrc file using the below commands to add it to the file and then source the file (you can manually source ROS every time but that defeats the point of making this a dedicated ROS development environment):

echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
source ~/.bashrc

A couple last things to do. For most ROS development you’ll want to be able to build your own packages. So we need a couple more packages in order to make this work. Install them with the following command:

sudo apt install python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential

We also need to initialize the dependency manager for ROS. Simply run these three commands:

sudo apt install python-rosdep
sudo rosdep init
rosdep update

And now let’s test the whole setup by trying to launch Rviz:

roscore & rosrun rviz rviz

If it worked you should now see a window like the one below:

Example of Rviz running in Windows through WSL2

And you’re done! Welcome to ROS on Windows!

Conclusion

Though this post is pretty long, none of this is actually too hard to setup and can be done in a matter of a few minutes (not including install times). It offers a painless way to get started in ROS development on Windows for those who don’t want to run a VM or dual-boot their systems.

Once everything has been done above, you’re ready for some ROS development. Not everything will be supported in ROS with this setup (GPU support is coming in the future), but the basics are all there for most development needs. If you’re new to ROS, I’d suggest walking through the tutorials here to get a handle on things. At least go through the Beginner Level (you can just do one or the other of the C++ and Python ones) so that you have a good foundation to work off of.

I hope this is helpful to somebody and if you have any thoughts on how to improve this tutorial don’t hesitate to let me know with a comment or an email.

50 thoughts on “Setting up ROS in Windows through WSL2

  1. I get stuck on the run xcalc step. I get the following error: Error: Can’t open display: {192.168.1.122}:0.0

    I used the Wifi adapter IP address of my computer. I also tried the vEthernet (WSL) address. Those are the only Ethernet adapters on my Surface Book. I have the VcXsrv X Server running and I can go into the tray and run the Xcalc app.

    Like

    1. Looks like you left in the curly braces around your IP address. Remove those and it should work. So in your .bashrc change the last line to: export DISPLAY=192.168.0.122:0.0

      Then you’ll need to close and restart your terminal window to reload the .bashrc file.

      Like

      1. It did fix it. Thank you. Can I use the vEthernet (WSL) address instead. I assume this one won’t change as often as my Wifi.

        Like

          1. I am getting a similar error even though I didn’t forget to remove the curly braces.
            The line in my bashrc is: export DISPLAY=192.168.1.20:0.0
            and my error is: qt.qpa.screen: QXcbConnection: Could not connect to display 192.168.1.20:0.0

            Also I noticed that the specific properties for Ethernet2 (the connection I’m using) say the IPv4 address is 192.168.1.20 but then if I go to hardware and connection properties and scroll down to Ethernet2, the IPv4 address is 192.168.1.20/24
            Regardless, neither address works.

            Like

            1. Do you have the X-server running on your machine? Go back the steps for “Setting up GUI forwarding” and follow them until you have VcXsrv running (you should see the icon for the app in the system tray on your taskbar). Then try running the command again.

              Like

              1. Yeah, it’s just a matter of running VcXsrv, right? I checked and unchecked everything I was supposed to and I saved my config. Then I clicked finish and a big black window popped up. I tried rosrun rviz rviz and got an error. I tried closing VcXsrv thinking “maybe it’ll open it automatically” and got the error again. I started VcXsrv again and this time tried running Xcalc. That works fine. So then I closed VcXsrv, went into my bashrc and added ‘export LIBGL_ALWAYS_INDIRECT=0’. I saved, exited and sourced my bashrc and then ran rosrun rviz rviz. Again the error. I’ve closed and reopened my terminal window multiple times and still nothing. Oh yeah, and I downloaded gedit but it is giving me the same error.

                Like

                1. Yes you need to have VcXsrv running whenever you want to run GUI apps from WSL. Don’t worry though as it doesn’t take up much resources. Whenever you want to run it just double click the config file you saved and it will launch with your saved settings.

                  Like

                    1. I get the same error: ‘qt.qpa.screen: QXcbConnection: Could not connect to display 192.168.1.20:0.0’
                      then it says ‘could not connect to any X display’

                      Like

  2. Launching xcalc worked with no particular errors but im hitting errors when running rviz.

    [ INFO] [1592450498.710676700]: rviz version 1.13.12
    [ INFO] [1592450498.711024100]: compiled against Qt version 5.9.5
    [ INFO] [1592450498.711252900]: compiled against OGRE version 1.9.0 (Ghadamon)
    [ INFO] [1592450498.718515200]: Forcing OpenGl version 0.
    Segmentation fault (core dumped)

    Any suggestions on what I should do would be greatly appreciated! Also thank you for this tutorial.

    Like

    1. Sounds like you need to try this fix:

      NOTE: Some people have said that they run into issues with OpenGL applications like Rviz. If you do, try setting the environment variable LIBGL_ALWAYS_INDIRECT=0 in your WSL2 terminal (you can just add export LIBGL_ALWAYS_INDIRECT=0 to the end of your .bashrc file).

      Like

      1. I had everything runnig then I tried imputing the command

        LIBGL_ALWAYS_INDIRECT=0

        Then everything stopped working. How can I disable this change?

        I’ve tried using this command but it doesn’t work
        export LIBGL_ALWAYS_INDIRECT=no

        Like

        1. To remove the variable you should be able to just do: export LIBGL_ALWAYS_INDIRECT=

          But for long term use you’ll also need to edit out the export command from your .bashrc file.

          Like

  3. Hi, I’m getting a segfault on trying to run rviz. The last log in the terminal says “Forcing OpenGL version 0,” which could be the problem? I configured the settings to not allow native openGL and disable control access.

    Like

        1. I did, kind of. It didn’t work, until I removed the zero at the end. I don’t know why. I’m not familiar with how to use the bashrc file. How can I permanently add it to the end?

          Is this correct:

          export LIBGL_ALWAYS_INDIRECT= ~/.bashrc

          Like

  4. Hey! Thanks so much for this tutorial – having it all in one place was great!

    I’m running into an issue when I try to run catkin_make on simple_arm package. I’m reasonably sure this is a WSL issue, which is why I’m asking here. I’m getting an issue with pthreads. It seemed like such an early stage of the ROS dev workflow, it probably has to do with setup.

    — ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    — ~~ traversing 1 packages in topological order:
    — ~~ – simple_arm
    — ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    — +++ processing catkin package: ‘simple_arm’
    — ==> add_subdirectory(simple_arm)
    — Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy
    CMake Error at /opt/ros/melodic/share/roscpp/cmake/roscppConfig.cmake:173 (message):
    Project ‘simple_arm’ tried to find library ‘pthread’. The library is
    neither a target nor built/installed properly. Did you compile project
    ‘roscpp’? Did you find_package() it before the subdirectory containing its
    code is included?
    Call Stack (most recent call first):
    /opt/ros/melodic/share/hardware_interface/cmake/hardware_interfaceConfig.cmake:197 (find_package)
    /opt/ros/melodic/share/controller_interface/cmake/controller_interfaceConfig.cmake:197 (find_package)
    /opt/ros/melodic/share/controller_manager/cmake/controller_managerConfig.cmake:197 (find_package)
    /opt/ros/melodic/share/catkin/cmake/catkinConfig.cmake:76 (find_package)
    simple_arm/CMakeLists.txt:10 (find_package)

    — Configuring incomplete, errors occurred!
    See also “/mnt/c/Users/katha/ROS/catkin_ws/build/CMakeFiles/CMakeOutput.log”.
    See also “/mnt/c/Users/katha/ROS/catkin_ws/build/CMakeFiles/CMakeError.log”.
    Makefile:320: recipe for target ‘cmake_check_build_system’ failed
    make: *** [cmake_check_build_system] Error 1
    Invoking “make cmake_check_build_system” failed

    I would really appreciate any help, thanks!

    Like

  5. I did look at that, but I had been running cmake 3.10.2, which I thought should be fine since it was below 3.13, which other people had issues with.

    Rather than downgrade I decided to upgrade, and it worked! (3.17.3).

    Like

  6. Hi,

    Thanks for that tutorial.

    Everything works fine for me to forward GUI but I have some troubles in communicating with a master node being on a remote machine.

    I define ROS_MASTER_URI=http://remote-machine-ip:11311.

    I can see the ROS environnement with a rostopic list but a rostopic echo /topic can’t display anything (no error message, nothing).

    Doing that from a third machine with a ubuntu environment works fine.

    Do you have any idea ?

    Like

    1. Hey Jeremy, glad you liked it!

      Networking is a little more complicated for ROS on WSL since it has to go through Windows. My first thought is that you need to make sure that you’ve opened up the right port(s) through the Windows firewall on your host machine.

      Like

  7. Hello~ jgkawell
    May you spend time for me?
    My question is: after we install successfully ROS in Windows, how to run ROS program on startup (bootup)?
    Thank you so much.

    Like

    1. Hey Van,

      Most of the time running ROS on startup is only really needed for a deployed system on a microcontroller or robot so I don’t know why you’d want to do this on a WSL machine. However, it is totally doable. Keep in mind though that “startup” doesn’t really happen the same way on WSL as it does on a true Linux install so things may be a bit different. I’ve included links to a couple sources if you want to try:

      If you’re wanting to know how to have ROS Master run on startup: https://blog.roverrobotics.com/how-to-run-ros-on-startup-bootup/

      If you’re wanting to know how to run a specific ROS node (or fleet of nodes): https://answers.ros.org/question/193181/how-to-start-a-ros-node-on-startup/

      Like

      1. Hi jgkawell,
        Thank you for your reply
        From you reply, you mean that basically WSL like Virtual Machine?

        For my project, I want to do like that
        1. Install WSL, ROS on Windows 10.
        2. Connect directly ROS on Windows 10 to motor driver.
        3. Control directly Robot by ROS on Windows 10, not through microcontroller.

        Is it impossible?

        Like

        1. Yes, WSL2 is basically a VM. A lightweight VM but one that is running on the Windows hypervisor. This means that (currently at least) there are some limitations with it. First is that you don’t get direct hardware support like GPU acceleration for graphics or ML. Another is that networking behaves slightly differently than if you had Linux as the host OS. But another big one is that you don’t have native device access to things like USB.

          I’m assuming you’re wanting to connect a motor controller to your PC via USB and then control it through ROS from there. I won’t go so far as to say this is impossible, but it will probably be difficult. The Windows team is working hard to provide the above missing features to WSL2 (GPU access is one thing coming very soon) but they’re not quite there yet.

          All that being said, there are ways to try and get USB devices to be accessible through WSL2. Here are a couple links to similar things others have done. I’d recommend reading through them to see if they can get you where you’re trying to go.

          https://github.com/microsoft/WSL/issues/5158
          https://github.com/jovton/USB-Storage-on-WSL2

          Like

          1. Hello~ jgkawell
            Thank you so much for your information.
            What WSL2 can work now except hypervisor?
            Can I make a map, localization from WSL2?
            And can we make a program to control mobile robot for WSL2?

            Like

            1. You can mostly think of WSL2 as just a standard virtual machine. Most anything will work like mapping or localization from sensor data. However, you don’t get proper hardware controls like GPU access or USB access so there are some limitations. As long as you can connect your ROS installation on WSL2 to your mobile robot via a network you can definitely make it control the robot.

              Like

  8. Amazing tutorial! I installed ROS2 Eloquent and after installing I tried to go through the official ros tutorial. It runs fine as long as I only need one window open, but for example if I try to open 2 terminals and have one as the demo talker and one as the demo listener, they dont seem to interact with each other. Same thing with turtlesim where I need 2 terminals open and they dont seem to be aware of each other. Any ideas how to fix this?
    Thanks!!

    Like

    1. Glad you liked it! I’ve actually never played around with ROS2 so I’m not sure what the issue might be. Can you do a rostopic list from each terminal and do they see each other there?

      Like

  9. Hey Jack – thanks for taking the time to put this together. I was able to go through your post and get Noetic installed successfully. Much appreciated.

    Like

  10. Thanks for the post.
    Initially I couldn’t get rviz working. I was getting an error: “error while loading shared libraries libqt5core.so.5 cannot open shared object file”.
    After some digging I found a solution which was to perform the following :

    sudo strip –remove-section=.note.ABI-tag /usr/./lib/x86_64-linux-gnu/libQt5Core.so.5

    I now have a fully functional rviz and Noetic installation on Ubuntu 20.04 on WSL2.

    Like

    1. Glad you liked it! Looking at the recommended specs for LGSVL it looks like it should run on WSL but the performance will not be great. WSL doesn’t have GPU support yet so any graphics intensive application will have a severe performance hit. This will be resolved in the future as Microsoft is adding GPU support soon though. I think autoware should work just fine though as that seems to be simply CPU and RAM dependent.

      Like

  11. When I try to open rviz, I get the errors:
    libGL error: No matching fbConfigs or visuals found libGL error: failed to load driver: swrast started roslaunch server http://Kadiya:51244/ ros_comm version 1.15.8

    SUMMARY ======== PARAMETERS * /rosdistro: noetic * /rosversion: 1.15.8 NODES auto-starting new master process[master]: started with pid [1236] ROS_MASTER_URI=http://Kadiya:11311/ setting /run_id to 01eb555e-251b-11eb-8d07-4889e732ffae process[rosout-1]: started with pid [1246] started core service [/rosout] [ INFO] [1605208350.573914500]: Forcing OpenGl version 0. libGL error: No matching fbConfigs or visuals found libGL error: failed to load driver: swrast Segmentation fault (core dumped)

    I tried the LIBGL_ALWAYS_INDIRECT=0 solution, adding it to bshrc and aslo sudo strip –remove-section=.note.ABI-tag /usr/./lib/x86_64-linux-gnu/libQt5Core.so.5.

    Nothing works.
    Other apps like gears and xcalc work great

    Does anyone know what to do?

    Like

    1. When I try to run gazebo, here are the errors:

      libGL error: No matching fbConfigs or visuals found libGL error: failed to load driver: swrast X Error of failed request: GLXBadContext Major opcode of failed request: 149 (GLX) Minor opcode of failed request: 5 (X_GLXMakeCurrent) Serial number of failed request: 42 Current serial number in output stream: 42

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s