noelex / rclnet

Modern ROS 2 client library for .NET.
MIT License
19 stars 2 forks source link

System.TypeInitializationException on new RclContext #15

Closed sedwick2048 closed 4 months ago

sedwick2048 commented 4 months ago

Attempting a simple program utilizing Rcl classes. My Program.cs:

using Rcl;

// Must add "somewhere in the source code of the project"
[assembly: System.Runtime.CompilerServices.DisableRuntimeMarshalling]

Console.WriteLine("Hello, World!  Today we're going to communicate over ROS2 using .NET.  Aren't you excited?!");
var whatToDo = Console.ReadLine();

if (whatToDo != null) {
  if (whatToDo.StartsWith("T", StringComparison.CurrentCultureIgnoreCase)) {
    // Talker
    await using var ctx = new RclContext(args);                       // EXCEPTION THROWN HERE
    using var node = ctx.CreateNode("SmplROS2dNET2");
    using var pub = node.CreatePublisher<Rosidl.Messages.Example.String>("/smpl");
    Console.WriteLine("Enter anything to publish a one-word message...");
    // User echos topic in another command window, enters letter, presses "Enter"...
    Console.ReadLine();
    pub.Publish(new Rosidl.Messages.Example.String("Published. "));
  } else if (whatToDo.StartsWith("L", StringComparison.CurrentCultureIgnoreCase)) {
    //TODO: listener
  }
}

At the line noted above, an exception happens, showing this information:

System.TypeInitializationException: 'The type initializer for 'Rcl.RclContext' threw an exception.' Inner Exception: DllNotFoundException: Unable to load DLL 'rcutils' or one of its dependencies: The specified module could not be found. (0x8007007E) This exception was originally thrown at this call stack: System.Runtime.InteropServices.NativeLibrary.LoadLibraryByName(string, System.Reflection.Assembly, System.Runtime.InteropServices.DllImportSearchPath?, bool) in NativeLibrary.cs Rcl.RclContext.RclContext()

I tried adding one of these two dependencies...

...but each time I browse to the DLL and hit "OK", I'm told the reference is invalid or unsupported.

Finally, since rclnet does not support IDLs currently, will I run into more trouble trying to use Rosidl.Messages.Example classes? Thanks...

noelex commented 4 months ago

Try running this project from a ROS2 command prompt.

You need to have a valid ROS2 environment to run nodes. You can setup the environment by either running setup.bat provided by ROS2, or if you’re using Visual Studio, configure the environment variables in launchSettings.json.

sedwick2048 commented 4 months ago

Can you please clarify what you mean by "ROS2 command prompt"? There's the Windows cmd, cmd run as administrator, PowerShell, PowerShell run as administrator, Visual Studio 2022 command prompt, and Visual Studio PowerShell. In most of those, I was able to get communication between two nodes after executing my .BAT file, so I'm pretty sure I have a "valid ROS2 environment":

image

I might have missed a Github page instruction, since I do not have a launchSettings.json file in my project--should I have added one, and if so, where? I would make it look like the one I tried modifying in RclExamples, which was:

{
  "profiles": {
    "Windows": {
      "commandName": "Project",
      "environmentVariables": {
        "ROS_DISTRO": "humble",
        "ROS_LOCALHOST_ONLY": "0",
        "ROS_PYTHON_VERSION": "3",
        "ROS_VERSION": "2",
        "PATH": "C:\\dev\\ros2_humble\\bin;C:\\Program Files\\OpenSSL-Win64\\bin;C\\ProgramData\\chocolatey\\lib\\tinyxml2\\lib",
        "AMENT_PREFIX_PATH": "C:\\dev\\ros2_humble"
      }
    }
  }
}
noelex commented 4 months ago

I mean “ROS2 command prompt” by a command prompt (be it cmd or powershell) which has setup ROS2 environment by calling setup.bat or local_setup.bat provided by your ROS distribution.

launchSettings.json is not specific to rclnet. It allows you to configure how Visual Studio and other IDEs should run or debug your application. You can read more about it here.

If you just want to launch your rclnet node from a ”ROS2 command prompt”, then you don’t a need a launchSettings.json, as the environment setup is already done by calling setup.bat or local_setup.bat.

sedwick2048 commented 4 months ago

I found out from other sites that:

  1. The launchSettings.json file should be in a folder named "Project", which is located in the project root.
  2. The launchSettings.json settings override the environment settings, so I just needed to make sure they matched.

Once I met these requirements, I then launched a debug session from Visual Studio no problem. I also ran an instance in release mode by executing the EXE in a command window after running ros2_humble\local_setup.bat.

sedwick2048 commented 4 months ago

Reopening due to new territory; I'm trying to get a Blazor app to communicate via ROS2. I have one .razor page utilizing some classes:

@page "/reactivROS2"
@using Rosidl.Runtime.Interop
@using Rcl

<table width="1500px">
  <tr>
    <td style="background-color:blueviolet;width:200px">
      <button @onclick="Publish">Publish</button>
    </td>
    </tr>
  <tr>
    <td style="font-size:20pt">
      <input @bind-value="@MsgToPub" />
    </td>
  </tr>
</table>

@code {
  string MsgToPub;

  private async void Publish(MouseEventArgs e) {
    var topic = "/blazor";
    await using var ctx = new RclContext();                         // EXCEPTION THROWN HERE
    using var node = ctx.CreateNode("BlazorROS2");
    using var pub = node.CreatePublisher<Rosidl.Messages.Example.String>(topic);
    pub.Publish(new Rosidl.Messages.Example.String(MsgToPub));
  }
}

My properly-located launchSettings.json, whose settings match the results of the batch file I don't think I can run from a Blazor app:

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:7892",
      "sslPort": 44355
    }
  },
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
      "applicationUrl": "http://localhost:5062",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ROS_DISTRO": "humble",
        "ROS_LOCALHOST_ONLY": "0",
        "ROS_PYTHON_VERSION": "3",
        "ROS_VERSION": "2",
        "PATH": "C:\\dev\\ros2_humble\\opt\\yaml_cpp_vendor\\bin;C:\\dev\\ros2_humble\\opt\\rviz_ogre_vendor\\bin;C:\\dev\\ros2_humble\\opt\\rviz_assimp_vendor\\bin;C:\\dev\\ros2_humble\\opt\\libcurl_vendor\\bin;C:\\dev\\ros2_humble\\Scripts;C:\\dev\\ros2_humble\\bin;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX86\\x86;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\VC\\VCPackages;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\MSBuild\\Current\\bin\\Roslyn;C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Common\\VSPerfCollectionTools\\vs2019\\;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v10.0A\\bin\\NETFX 4.8 Tools\\;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\FSharp\\Tools;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Team Tools\\DiagnosticsHub\\Collector;C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.22621.0\\\\x86;C:\\Program Files (x86)\\Windows Kits\\10\\bin\\\\x86;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\\\MSBuild\\Current\\Bin\\amd64;C:\\WINDOWS\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\Tools\\;C:\\Python38\\Scripts\\;C:\\Python38\\;C:\\Program Files (x86)\\VMware\\VMware Workstation\\bin\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Matrox Imaging\\Mil\\DLL;C:\\Program Files\\Matrox Imaging\\Tools;C:\\Program Files\\Microsoft SQL Server\\150\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\OpenSSL-Win64\\bin\\;C:\\opencv\\x64\\vc16\\bin;C:\\Program Files\\CMake\\bin;C:\\ProgramData\\chocolatey\\lib\\cunit\\lib;C:\\ProgramData\\chocolatey\\lib\\tinyxml2\\lib;C:\\ProgramData\\chocolatey\\lib\\bullet\\lib;C:\\Program Files\\Graphviz\\bin;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\;C:\\Program Files\\dotnet\\;C:\\Program Files (x86)\\Windows Kits\\10\\Windows Performance Toolkit\\;C:\\Users\\REDACTED\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\REDACTED\\AppData\\Local\\GitHubDesktop\\bin;C:\\Users\\REDACTED\\.dotnet\\tools;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\CMake\\bin;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\Ninja;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\VC\\Linux\\bin\\ConnectionManagerExe;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\vcpkg",
        "AMENT_PREFIX_PATH": "C:\\dev\\ros2_humble;C:\\dev\\ROS2cs\\install"
      }
    },
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
      "applicationUrl": "https://localhost:7076;http://localhost:5062",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ROS_DISTRO": "humble",
        "ROS_LOCALHOST_ONLY": "0",
        "ROS_PYTHON_VERSION": "3",
        "ROS_VERSION": "2",
        "PATH": "C:\\dev\\ros2_humble\\opt\\yaml_cpp_vendor\\bin;C:\\dev\\ros2_humble\\opt\\rviz_ogre_vendor\\bin;C:\\dev\\ros2_humble\\opt\\rviz_assimp_vendor\\bin;C:\\dev\\ros2_humble\\opt\\libcurl_vendor\\bin;C:\\dev\\ros2_humble\\Scripts;C:\\dev\\ros2_humble\\bin;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX86\\x86;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\VC\\VCPackages;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\MSBuild\\Current\\bin\\Roslyn;C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Common\\VSPerfCollectionTools\\vs2019\\;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v10.0A\\bin\\NETFX 4.8 Tools\\;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\FSharp\\Tools;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Team Tools\\DiagnosticsHub\\Collector;C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.22621.0\\\\x86;C:\\Program Files (x86)\\Windows Kits\\10\\bin\\\\x86;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\\\MSBuild\\Current\\Bin\\amd64;C:\\WINDOWS\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\Tools\\;C:\\Python38\\Scripts\\;C:\\Python38\\;C:\\Program Files (x86)\\VMware\\VMware Workstation\\bin\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Matrox Imaging\\Mil\\DLL;C:\\Program Files\\Matrox Imaging\\Tools;C:\\Program Files\\Microsoft SQL Server\\150\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\OpenSSL-Win64\\bin\\;C:\\opencv\\x64\\vc16\\bin;C:\\Program Files\\CMake\\bin;C:\\ProgramData\\chocolatey\\lib\\cunit\\lib;C:\\ProgramData\\chocolatey\\lib\\tinyxml2\\lib;C:\\ProgramData\\chocolatey\\lib\\bullet\\lib;C:\\Program Files\\Graphviz\\bin;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\;C:\\Program Files\\dotnet\\;C:\\Program Files (x86)\\Windows Kits\\10\\Windows Performance Toolkit\\;C:\\Users\\REDACTED\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\REDACTED\\AppData\\Local\\GitHubDesktop\\bin;C:\\Users\\REDACTED\\.dotnet\\tools;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\CMake\\bin;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\Ninja;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\VC\\Linux\\bin\\ConnectionManagerExe;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\vcpkg",
        "AMENT_PREFIX_PATH": "C:\\dev\\ros2_humble;C:\\dev\\ROS2cs\\install"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ROS_DISTRO": "humble",
        "ROS_LOCALHOST_ONLY": "0",
        "ROS_PYTHON_VERSION": "3",
        "ROS_VERSION": "2",
        "PATH": "C:\\dev\\ros2_humble\\opt\\yaml_cpp_vendor\\bin;C:\\dev\\ros2_humble\\opt\\rviz_ogre_vendor\\bin;C:\\dev\\ros2_humble\\opt\\rviz_assimp_vendor\\bin;C:\\dev\\ros2_humble\\opt\\libcurl_vendor\\bin;C:\\dev\\ros2_humble\\Scripts;C:\\dev\\ros2_humble\\bin;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\Tools\\MSVC\\14.39.33519\\bin\\HostX86\\x86;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\VC\\VCPackages;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\MSBuild\\Current\\bin\\Roslyn;C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Common\\VSPerfCollectionTools\\vs2019\\;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v10.0A\\bin\\NETFX 4.8 Tools\\;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\FSharp\\Tools;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Team Tools\\DiagnosticsHub\\Collector;C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.22621.0\\\\x86;C:\\Program Files (x86)\\Windows Kits\\10\\bin\\\\x86;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\\\MSBuild\\Current\\Bin\\amd64;C:\\WINDOWS\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\Tools\\;C:\\Python38\\Scripts\\;C:\\Python38\\;C:\\Program Files (x86)\\VMware\\VMware Workstation\\bin\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Matrox Imaging\\Mil\\DLL;C:\\Program Files\\Matrox Imaging\\Tools;C:\\Program Files\\Microsoft SQL Server\\150\\Tools\\Binn\\;C:\\Program Files\\Microsoft SQL Server\\Client SDK\\ODBC\\170\\Tools\\Binn\\;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\OpenSSL-Win64\\bin\\;C:\\opencv\\x64\\vc16\\bin;C:\\Program Files\\CMake\\bin;C:\\ProgramData\\chocolatey\\lib\\cunit\\lib;C:\\ProgramData\\chocolatey\\lib\\tinyxml2\\lib;C:\\ProgramData\\chocolatey\\lib\\bullet\\lib;C:\\Program Files\\Graphviz\\bin;C:\\Program Files\\Microsoft SQL Server\\130\\Tools\\Binn\\;C:\\Program Files\\dotnet\\;C:\\Program Files (x86)\\Windows Kits\\10\\Windows Performance Toolkit\\;C:\\Users\\REDACTED\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\REDACTED\\AppData\\Local\\GitHubDesktop\\bin;C:\\Users\\REDACTED\\.dotnet\\tools;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\CMake\\bin;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\Ninja;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\Common7\\IDE\\VC\\Linux\\bin\\ConnectionManagerExe;C:\\Program Files\\Microsoft Visual Studio\\2022\\Professional\\VC\\vcpkg",
        "AMENT_PREFIX_PATH": "C:\\dev\\ros2_humble;C:\\dev\\ROS2cs\\install"
      }
    }
  }
}

Again, attempting to add rcutils.dll as a project dependency produces a "reference is invalid or unsupported" message. Any insight is appreciated, thanks.

noelex commented 4 months ago

Have you tried running the application from command line?

sedwick2048 commented 4 months ago

I'm not sure that's possible; Blazor pages are executed in a browser.

noelex commented 4 months ago

I presume that you’re using server-side rendering or exposing ROS related operations via Web API, and you can run the server with ROS environment variables properly configured.

It’s impossible to load native libraries from inside the sandboxed environment of the browser.

sedwick2048 commented 4 months ago

I think I might need client-side for optimally responsive UX, but I'll try server-side in a little bit. I've attempted to dotnet run a Blazor app from the prepared command line, and while it runs and indicates no errors, it doesn't get any messages published either.

noelex commented 4 months ago

Might be due to this?

sedwick2048 commented 4 months ago

No, according to a try/catch block I added around the Publish method lines, It's saying The type initializer for 'Rcl.RclContext' threw an exception. This is after executing dotnet run in a command window where I ran the ROS2 setup (and also published from), and then manipulated the page from a browser pointed at by the Now listening on: address displayed in that command window.

noelex commented 4 months ago

What's the render mode of your Blazor page?

You can also try accessing RclContext in entrypoint of the program to see if that works.

sedwick2048 commented 4 months ago

I'm pretty new to Blazor as well--how do I find out the render mode and where is the "entrypoint"?

noelex commented 4 months ago

You can read more about render modes here.

Entrypoint is where the app starts its execution. It’s usually inside Program.cs.

sedwick2048 commented 4 months ago

I don't specify a render mode anywhere, so according to that page, "By default, components use static server-side rendering (static SSR)", so that?

My Program.cs now looks like this:

using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Test_Blazor4;
using Rcl;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

await builder.Build().RunAsync();
Console.WriteLine("The wind-up..."); 
await using var ctx = new RclContext();
using var node = ctx.CreateNode("BlazorROS2dNETProg");
using var pub = node.CreatePublisher<Rosidl.Messages.Example.String>("/blazor");
pub.Publish(new Rosidl.Messages.Example.String("Please hear this"));
Console.WriteLine("...and the pitch...");

No additional errors happened when I ran, and I didn't see any console lines written out either.

noelex commented 4 months ago

You need to place your code before await builder.Build().RunAsync(); because RunAsync won’t return until the program exits.

sedwick2048 commented 4 months ago

Changed to this:

try {
  Console.WriteLine("The wind-up...");
  await using var ctx = new RclContext();
  using var node = ctx.CreateNode("BlazorROS2dNETProg");
  using var pub = node.CreatePublisher<Rosidl.Messages.Example.String>("/blazor");
  pub.Publish(new Rosidl.Messages.Example.String("Please hear this"));
  Console.WriteLine("...and the pitch...");
} catch (Exception ex) {
  Console.WriteLine(ex.Message);
}

await builder.Build().RunAsync();

Got this in Edge Developer Tools console:

The wind-up...
The type initializer for 'Rcl.RclContext' threw an exception.
noelex commented 4 months ago

Sorry I missed this line var builder = WebAssemblyHostBuilder.CreateDefault(args);.

This means that you're using Blazor WebAssembly and the app will run in the browser. Please create a new project using the Blazor Web App template.

sedwick2048 commented 4 months ago

Done. Program.cs now looks like:

using GSUI8_BWA.Components;
using Rcl;

namespace GSUI8_BWA {
  public class Program {
    public static void Main(string[] args) {
      var builder = WebApplication.CreateBuilder(args);

      // Add services to the container.
      builder.Services.AddRazorComponents().AddInteractiveServerComponents();
      var app = builder.Build();

      // Configure the HTTP request pipeline.
      if (!app.Environment.IsDevelopment()) {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
      }

      app.UseHttpsRedirection();
      app.UseStaticFiles();
      app.UseAntiforgery();
      app.MapRazorComponents<App>().AddInteractiveServerRenderMode();

      try {
        Console.WriteLine("The wind-up...");
        /*await*/ using var ctx = new RclContext();
        using var node = ctx.CreateNode("BlazorROS2dNETProg");
        using var pub = node.CreatePublisher<Rosidl.Messages.Example.String>("/blazor");
        pub.Publish(new Rosidl.Messages.Example.String("Please hear this"));
        Console.WriteLine("...and the pitch...");
      } catch (Exception ex) {
        Console.WriteLine(ex.Message);
      }

      app.Run();
    }
  }
}

Execution command window:

C:\dev\GSUI8_BWA>dotnet run
Building...
The wind-up...
...and the pitch...
[WARN] [1716221357.842970200] [BlazorROS2dNETProg]: Received IncompatibleQosEvent on publisher of topic '/blazor': Total = 1, Delta = 1, PolicyKind = Durability
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5155
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\dev\GSUI8_BWA

Listening command window: [WARN] [1716221358.115239800] [_ros2cli_43764]: New publisher discovered on topic '/blazor', offering incompatible QoS. No messages will be received from it. Last incompatible policy: DURABILITY

EDIT: When following the link, this is added to the bottom of the execution window:

warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
      Failed to determine the https port for redirect.

My .razor page mechanism doesn't publish either, but also gives no errors.

sedwick2048 commented 4 months ago

UPDATE: I restarted my listener, and while the web page still can't publish, the Program.cs message ("Please hear this") did get out on run. The initial setting for pub.ActualQos.Durability is Volatile, I'll see if I can init it to TransientLocal and if the listener likes that.

FURTHER UPDATE: doesn't look like I can set it. Guess I need to figure out how the browser action needs to submit data back to the server code.

sedwick2048 commented 4 months ago

Yeah, I really thought the code {...} block of a Razor page in a Blazor web app gets executed on the server, but this didn't work:

@page "/ROS2"
@rendermode InteractiveServer
@using Rosidl.Runtime.Interop
@using Rcl
@using BWA.ROS2

      <input @bind-value="@MsgToPub" />
      <button @onclick="Publish">Publish</button>
      <input @bind-value="@ErrMsg" style="color:red" />

@code {
  string MsgToPub;
  string ErrMsg;

  private async void Publish(MouseEventArgs e) {
    try {
      await using var ctx = new RclContext();
      using var node = ctx.CreateNode("BlazorROS2dNET");
      using var pub = node.CreatePublisher<Rosidl.Messages.Example.String>("/blazor");
      pub.Publish(new Rosidl.Messages.Example.String(MsgToPub));
      Console.WriteLine("Sent from the server now, I hope.");     // This gets written out on the console, at least
    } catch (Exception exc) {
      ErrMsg = exc.Message;
    }
  }
}

So, then I created a Blazor solution with three projects: Server, Client, and Shared (I think VS called it a "hosted Blazor app" template?). I can get the publish to happen in the server project's Program.cs, and I can get a Razor page on the client to do a get request on a controller on the server.

In the client page, after filling in an input and clicking a button: Results = await Http.GetStringAsync($"ROS2?toPublish={MsgToPub}&requestID={reqID++}");

Server-side controller:

using Microsoft.AspNetCore.Mvc;
using Rcl;

namespace Blazor3.Server.Controllers {
  [ApiController]
  [Route("[controller]")]
  public class ROS2Controller : ControllerBase {
    [HttpGet]
    public string Get([FromQuery] string toPublish, [FromQuery] int requestID) {
      var resp = string.Empty;

      try {
        Console.WriteLine("Here comes the...");
        using var ctx = new RclContext();
        using var node = ctx.CreateNode("Blazor3Cntrlr");
        using var pub = node.CreatePublisher<Rosidl.Messages.Example.String>("/blazor");
        pub.Publish(new Rosidl.Messages.Example.String(toPublish));
        Console.WriteLine("BOOM");
      } catch (Exception exc) {
        resp = exc.Message;
      }

      resp += $" Publishing {toPublish} (reqID {requestID})";
      return resp;
    }
  }
}

The Console.WriteLines happen but never the publish of toPublish, and no exceptions occur. What should I try next? Thanks...

noelex commented 4 months ago

Please check this out.

sedwick2048 commented 4 months ago

Funny, shortly before checking your latest comment I thought, "Maybe the RclContextneeds to be a singleton." So I added a line to Program.cs:

      builder.Services.AddSingleton<RclContext>();
      var app = builder.Build();

and updated my Razor file:

@inject RclContext DoROS2

Publish still looks like above, only without the new RclContext() line. Now it does publish, but ONLY if I put a breakpoint at the Publish call, step over it (not too quickly), then run.

I tried replacing the Publish call in the Razor file with await pub.PublishAsync, but this only worked for the first call.

I am uncertain on the syntax to access the singleton from my ROS2Controller.

sedwick2048 commented 4 months ago

Figured some things out and now it publishes every time! The necessary syntax in Program.cs, which unfortunately wasn't shown in Issue #10, should have been:

      var ctx = new RclContext();
      var node = ctx.CreateNode("BlazorROS2dNETProg");
      var pub = node.CreatePublisher<Rosidl.Messages.Example.String>("/blazor"); 
      builder.Services.AddSingleton(ctx);
      builder.Services.AddSingleton(node);    // Even necessary for I'm currently doing?
      builder.Services.AddSingleton(pub);
      var app = builder.Build();

And then my Razor page does:

@inject RclContext DoROS2
@inject IRclPublisher<Rosidl.Messages.Example.String> WRHearst
...
      WRHearst.Publish(new Rosidl.Messages.Example.String(MsgToPub));

or

      await WRHearst.PublishAsync(new Rosidl.Messages.Example.String(MsgToPub));

Still not sure how to retrieve a singleton from inside a controller file, but I'll cross that bridge if I need to.

Closing this out until I discover more problems. Thanks again!