├── .editorconfig ├── .gitattributes ├── .github ├── CODE_OF_CONDUCT.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug.yml │ └── config.yml ├── README.md ├── SUPPORT.md └── workflows │ └── publish.yml ├── .gitignore ├── Directory.Build.props ├── LICENSE ├── NOTICE ├── RELEASE ├── Robots.slnx ├── build ├── Assets │ ├── Icons.ai │ ├── icon128.png │ ├── iconRhino128.png │ ├── iconRobot.png │ └── social.svg └── Robots.Build │ ├── Program.cs │ └── Robots.Build.csproj ├── docs ├── Bartlett │ ├── Adhesive_extruder.3dm │ ├── Flange.3dm │ ├── IO_layout.PNG │ └── IO_layout.pdf ├── Images │ ├── coordinate system.png │ ├── iconRobot.svg │ └── logo.png └── Sponsors │ ├── Bmade_dark.png │ └── Bmade_light.png ├── lib ├── ABB.Robotics.Controllers.PC.dll ├── Newtonsoft.Json.Rhino.dll ├── RobotStudio.Services.RobApi.Desktop.dll └── RobotStudio.Services.RobApi.dll ├── samples ├── Robots.Samples.Dynamo │ ├── DynamoMeshPoser.cs │ ├── Geometry.cs │ ├── Program.cs │ ├── Robot.cs │ ├── Robots.Samples.Dynamo.csproj │ ├── RobotsViewExtension.cs │ └── package │ │ ├── bin │ │ └── Robots.Dynamo_DynamoCustomization.xml │ │ ├── extra │ │ └── Robots.Dynamo_ViewExtensionDefinition.xml │ │ └── pkg.json ├── Robots.Samples.Grasshopper │ ├── Python script example.gh │ ├── extrusion example.gh │ ├── metal forming example.gh │ ├── pick and place example.gh │ ├── positioner example.gh │ └── simple example.gh ├── Robots.Samples.Unity │ ├── .gitattributes │ ├── .gitignore │ ├── Assets │ │ ├── CameraSimple.cs │ │ ├── CameraSimple.cs.meta │ │ ├── Floor.mat │ │ ├── Floor.mat.meta │ │ ├── Material.mat │ │ ├── Material.mat.meta │ │ ├── Robot.cs │ │ ├── Robot.cs.meta │ │ ├── Robots.Samples.Unity.asmdef │ │ ├── Robots.Samples.Unity.asmdef.meta │ │ ├── Scene.unity │ │ ├── Scene.unity.meta │ │ ├── TestProgram.cs │ │ ├── TestProgram.cs.meta │ │ ├── URP-Global.asset │ │ ├── URP-Global.asset.meta │ │ ├── URP-Renderer.asset │ │ ├── URP-Renderer.asset.meta │ │ ├── URP.asset │ │ ├── URP.asset.meta │ │ ├── UnityMeshPoser.cs │ │ ├── UnityMeshPoser.cs.meta │ │ ├── Volume.asset │ │ ├── Volume.asset.meta │ │ ├── csc.rsp │ │ └── csc.rsp.meta │ ├── Packages │ │ ├── manifest.json │ │ └── packages-lock.json │ ├── ProjectSettings │ │ ├── EditorSettings.asset │ │ ├── GraphicsSettings.asset │ │ ├── PackageManagerSettings.asset │ │ ├── ProjectSettings.asset │ │ ├── ProjectVersion.txt │ │ ├── QualitySettings.asset │ │ ├── ShaderGraphSettings.asset │ │ └── URPProjectSettings.asset │ └── README.md └── Robots.Samples.Wpf │ ├── App.xaml │ ├── App.xaml.cs │ ├── HelixMeshPoser.cs │ ├── MainViewModel.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── Robots.Samples.Wpf.csproj │ └── TestProgram.cs ├── src ├── Robots.Grasshopper │ ├── Assets │ │ └── Embed │ │ │ ├── iconAngles.png │ │ │ ├── iconCheckCollisions.png │ │ │ ├── iconCommandParam.png │ │ │ ├── iconCreateFrame.png │ │ │ ├── iconCreateProgram.png │ │ │ ├── iconCreateTarget.png │ │ │ ├── iconCreateTool.png │ │ │ ├── iconCustomCode.png │ │ │ ├── iconCustomCommand.png │ │ │ ├── iconDeconstructProgramTarget.png │ │ │ ├── iconDeconstructTarget.png │ │ │ ├── iconDeconstructToolpath.png │ │ │ ├── iconFrame.png │ │ │ ├── iconFrameParam.png │ │ │ ├── iconGetPlane.png │ │ │ ├── iconGroupCommand.png │ │ │ ├── iconJointsParam.png │ │ │ ├── iconKinematics.png │ │ │ ├── iconMessage.png │ │ │ ├── iconPostProcessorParam.png │ │ │ ├── iconProgramParam.png │ │ │ ├── iconPulseDO.png │ │ │ ├── iconRobot.png │ │ │ ├── iconRobotParam.png │ │ │ ├── iconSave.png │ │ │ ├── iconSetAO.png │ │ │ ├── iconSetDO.png │ │ │ ├── iconSimpleTrail.png │ │ │ ├── iconSimulation.png │ │ │ ├── iconSpeed.png │ │ │ ├── iconSpeedParam.png │ │ │ ├── iconStopCommand.png │ │ │ ├── iconTargetParam.png │ │ │ ├── iconToPlane.png │ │ │ ├── iconTool.png │ │ │ ├── iconToolParam.png │ │ │ ├── iconToolpathParam.png │ │ │ ├── iconURRemote.png │ │ │ ├── iconWait.png │ │ │ ├── iconWaitDI.png │ │ │ └── iconZoneParam.png │ ├── Commands │ │ ├── CustomCommand.cs │ │ ├── Group.cs │ │ ├── Message.cs │ │ ├── PulseDO.cs │ │ ├── SetAO.cs │ │ ├── SetDO.cs │ │ ├── Stop.cs │ │ ├── Wait.cs │ │ └── WaitDI.cs │ ├── ComponentButton.cs │ ├── ComponentForm.cs │ ├── Goos │ │ ├── GH_Command.cs │ │ ├── GH_Frame.cs │ │ ├── GH_Joints.cs │ │ ├── GH_PostProcessor.cs │ │ ├── GH_Program.cs │ │ ├── GH_RobotSystem.cs │ │ ├── GH_Speed.cs │ │ ├── GH_Target.cs │ │ ├── GH_Tool.cs │ │ ├── GH_Toolpath.cs │ │ └── GH_Zone.cs │ ├── Obsolete │ │ ├── CreateProgram.cs │ │ ├── CreateSpeed.cs │ │ └── Custom.cs │ ├── Parameters │ │ ├── CommandParameter.cs │ │ ├── FrameParameter.cs │ │ ├── JointsParameter.cs │ │ ├── PostProcessorParameter.cs │ │ ├── ProgramParameter.cs │ │ ├── RobotSystemParameter.cs │ │ ├── SpeedParameter.cs │ │ ├── TargetParameter.cs │ │ ├── ToolParameter.cs │ │ ├── ToolpathParameter.cs │ │ └── ZoneParameter.cs │ ├── Program │ │ ├── CheckCollisions.cs │ │ ├── CreateProgramVariable.cs │ │ ├── CustomCode.cs │ │ ├── DeconstructProgramTargets.cs │ │ ├── Remote.cs │ │ ├── SaveProgram.cs │ │ ├── Simulation.cs │ │ └── SimulationForm.cs │ ├── RobotSystem │ │ ├── DegreesToRadians.cs │ │ ├── FromPlane.cs │ │ ├── GetPlane.cs │ │ ├── Kinematics.cs │ │ ├── LibraryForm.cs │ │ ├── LibraryParam.cs │ │ ├── LoadFrame.cs │ │ ├── LoadRobotSystem.cs │ │ └── LoadTool.cs │ ├── Robots.Grasshopper.csproj │ ├── RobotsInfo.cs │ ├── Target │ │ ├── ConfigParam.cs │ │ ├── CreateFrame.cs │ │ ├── CreateSpeedAccel.cs │ │ ├── CreateTarget.cs │ │ ├── CreateTool.cs │ │ ├── DeconstructTarget.cs │ │ └── DeconstructToolpath.cs │ ├── Util.cs │ ├── Visualization │ │ └── DrawSimpleTrail.cs │ └── build │ │ └── Robots.Rhino.targets └── Robots │ ├── Commands │ ├── Command.cs │ ├── Custom.cs │ ├── Group.cs │ ├── Message.cs │ ├── PulseDO.cs │ ├── SetAO.cs │ ├── SetDO.cs │ ├── Stop.cs │ ├── Wait.cs │ └── WaitDI.cs │ ├── Geometry │ ├── CircumcentreSolver.cs │ └── Vector6d.cs │ ├── IO │ ├── CleanFile3dm.cs │ ├── FileIO.cs │ ├── OnlineLibrary.cs │ └── Settings.cs │ ├── Kinematics │ ├── CustomKinematics.cs │ ├── KinematicSolution.cs │ ├── MechanicalGroupKinematics.cs │ ├── MechanismKinematics.cs │ ├── NumericalKinematics.cs │ ├── OffsetWristKinematics.cs │ ├── PositionerKinematics.cs │ ├── RobotCellKinematics.cs │ ├── RobotKinematics.cs │ ├── SphericalWristKinematics.cs │ └── TrackKinematics.cs │ ├── Mechanisms │ ├── Custom.cs │ ├── Joints.cs │ ├── Mechanism.cs │ ├── Positioner.cs │ └── Track.cs │ ├── PostProcessors │ ├── DrlPostProcessor.cs │ ├── FanucPostProcessor.cs │ ├── FrankxPostProcessor.cs │ ├── IgusPostProcessor.cs │ ├── JKSPostProcessor.cs │ ├── KRLPostProcessor.cs │ ├── RapidPostProcessor.cs │ ├── URScriptPostProcessor.cs │ └── VAL3PostProcessor.cs │ ├── Program │ ├── CellTarget.cs │ ├── CheckProgram.cs │ ├── Collision.cs │ ├── CustomProgram.cs │ ├── Program.cs │ ├── ProgramTarget.cs │ └── Simulation.cs │ ├── Remotes │ ├── Ftp.cs │ ├── IRemote.cs │ ├── RemoteAbb.cs │ ├── RemoteFranka.cs │ ├── RemoteUR.cs │ ├── RemoteURFtp.cs │ ├── RemoteURPrimaryClient.cs │ ├── URRealTime.cs │ ├── URRealTimeDataExchange.cs │ └── User.cs │ ├── Resources │ ├── URRTDE.csv │ ├── URRealTime.csv │ └── UrpTemplate.txt │ ├── RobotArms │ ├── RobotAbb.cs │ ├── RobotArm.cs │ ├── RobotDoosan.cs │ ├── RobotFanuc.cs │ ├── RobotFranka.cs │ ├── RobotIgus.cs │ ├── RobotJaka.cs │ ├── RobotKuka.cs │ ├── RobotStaubli.cs │ └── RobotUR.cs │ ├── RobotSystems │ ├── CobotSystem.cs │ ├── IO.cs │ ├── IndustrialSystem.cs │ ├── MechanicalGroup.cs │ ├── RobotSystem.cs │ ├── SystemAbb.cs │ ├── SystemDoosan.cs │ ├── SystemFanuc.cs │ ├── SystemFranka.cs │ ├── SystemIgus.cs │ ├── SystemJaka.cs │ ├── SystemKuka.cs │ ├── SystemStaubli.cs │ └── SystemUR.cs │ ├── Robots.csproj │ ├── TargetAttributes │ ├── Frame.cs │ ├── Speed.cs │ ├── TargetAttribute.cs │ ├── Tool.cs │ └── Zone.cs │ ├── Targets │ ├── CartesianTarget.cs │ ├── JointTarget.cs │ ├── Target.cs │ └── Toolpath.cs │ ├── Util.cs │ └── Visualization │ ├── MeshPoser.cs │ ├── RhinoMeshPoser.cs │ └── SimpleTrail.cs └── tests └── Robots.Tests ├── ABBTests.cs ├── Performance.cs ├── Program.cs ├── Robots.Tests.csproj └── URTests.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project adheres to the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct). -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: visose 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: visose.com/paypal 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug 2 | description: File a bug 3 | title: "[Bug] " 4 | labels: ["bug"] 5 | body: 6 | - type: checkboxes 7 | id: searched 8 | attributes: 9 | label: Is there an existing issue for this? 10 | description: Please search to see if an issue or discussion already exists for the bug you encountered. 11 | options: 12 | - label: I have searched the existing issues 13 | required: true 14 | - type: input 15 | id: robotsVersion 16 | attributes: 17 | label: What Robots version are you using? 18 | description: You can find the version number using the _PackageManager command. Please check if the bug exists on the latest version. 19 | placeholder: "1.0.1" 20 | validations: 21 | required: true 22 | - type: dropdown 23 | id: rhinoVersion 24 | attributes: 25 | label: What Rhino version are you using? 26 | description: Only Rhino 7 and 8 for Windows and MacOS are supported. 27 | options: 28 | - Rhino 7 for Windows 29 | - Rhino 7 for MacOS 30 | - Rhino 8 for Windows 31 | - Rhino 8 for MacOS 32 | - Other 33 | validations: 34 | required: true 35 | - type: textarea 36 | id: behavior 37 | attributes: 38 | label: Current Behavior 39 | description: A concise description of what you're experiencing. 40 | validations: 41 | required: true 42 | - type: textarea 43 | id: expected 44 | attributes: 45 | label: Expected Behavior 46 | description: A concise description of what you expected to happen. 47 | validations: 48 | required: false 49 | - type: textarea 50 | id: steps 51 | attributes: 52 | label: Steps To Reproduce 53 | description: Steps to reproduce the behavior. 54 | validations: 55 | required: false 56 | - type: textarea 57 | id: other 58 | attributes: 59 | label: Anything else? 60 | description: | 61 | Links, references, or anything that will give us more context about the issue you are encountering! 62 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 63 | validations: 64 | required: false 65 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 💬 Discussions 4 | url: https://github.com/visose/Robots/discussions/new?category=q-a 5 | about: Ask a question -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | ## Support 2 | 3 | If you have a question, or need help: 4 | 1. Check out the [docs](../../../wiki) 5 | 1. Search the [discussions](https://github.com/visose/Robots/discussions) 6 | 1. Ask a question [here](https://github.com/visose/Robots/discussions/new?category=q-a) 7 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | workflow_dispatch: 8 | inputs: 9 | commands: 10 | description: 'Commands' 11 | required: true 12 | default: 'debug' 13 | 14 | jobs: 15 | publish: 16 | runs-on: windows-2022 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | - run: dotnet run --project "build/Robots.Build/Robots.Build.csproj" ${{ github.event.inputs.commands }} 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | YAK_TOKEN: ${{ secrets.YAK_TOKEN }} 24 | NUGET_KEY: ${{ secrets.NUGET_KEY }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | nupkg/ 3 | secrets* 4 | 5 | # Build results 6 | artifacts/ 7 | 8 | # Visual Studio Code 9 | .vscode 10 | 11 | # Rider 12 | .idea 13 | 14 | # Visual Studio 15 | .vs/ 16 | 17 | # User-specific files 18 | *.suo 19 | *.user 20 | *.userosscache 21 | *.sln.docstates -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | <Project> 2 | 3 | <PropertyGroup> 4 | <Product>Robots</Product> 5 | <Version>1.9.0</Version> 6 | <Authors>Robots Authors</Authors> 7 | <Description>Create and simulate ABB, KUKA, UR, and Staubli robot programs.</Description> 8 | <PackageTags>Robots;ABB;KUKA;UR;Staubli;Robotics</PackageTags> 9 | <PackageProjectUrl>https://github.com/visose/robots</PackageProjectUrl> 10 | <Icon>iconRobot.png</Icon> 11 | <ReleaseNotes>RELEASE</ReleaseNotes> 12 | 13 | <CurrentYear>$([System.DateTime]::Now.Year)</CurrentYear> 14 | <Copyright>Copyright (c) 2015-$(CurrentYear) $(Authors)</Copyright> 15 | <Company>$(Authors) - $(PackageProjectUrl)</Company> 16 | <PackageLicenseExpression>MIT</PackageLicenseExpression> 17 | <RepositoryUrl>https://github.com/visose/robots.git</RepositoryUrl> 18 | </PropertyGroup> 19 | 20 | <PropertyGroup> 21 | <LangVersion>latest</LangVersion> 22 | <Nullable>enable</Nullable> 23 | <ImplicitUsings>enable</ImplicitUsings> 24 | <AnalysisLevel>latest</AnalysisLevel> 25 | <NoWarn>MSB3270</NoWarn> 26 | <RootDir>$(MSBuildThisFileDirectory)</RootDir> 27 | <ArtifactsPath>$(RootDir)artifacts</ArtifactsPath> 28 | </PropertyGroup> 29 | 30 | </Project> 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015 Robots Authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Robots uses third-party libraries or other resources that may be 2 | distributed under licenses different than the Robots software. 3 | 4 | In the event that we accidentally failed to list a required notice, please 5 | bring it to our attention. 6 | 7 | Kdl.NetStandard (MIT) 8 | * Copyright (c) 2020 Doug Slater 9 | * https://github.com/slater1/Kdl.NetStandard/blob/master/LICENSE 10 | 11 | Orocos KDL (LGPL-v2) 12 | * Copyright (с) Orocos 13 | * https://www.orocos.org/content/orocos-licenses 14 | 15 | Math.NET (MIT) 16 | * Copyright (с) 2002-2022 Math.NET 17 | * https://github.com/mathnet/mathnet-numerics/blob/master/LICENSE-MKL.md 18 | 19 | OPW Kinematics (Apache-2.0) 20 | * Copyright (с) Jonathan Meyer 21 | * https://github.com/Jmeyer1292/opw_kinematics/blob/master/LICENSE 22 | 23 | Frankx (LGPL-3.0) 24 | * Copyright (с) Lars Berscheid 25 | * https://github.com/pantor/frankx/blob/master/LICENSE 26 | 27 | ROS-Industrial Support for Universal Robots (BSD, 3-Clause) 28 | * Copyright (с) Felix Messmer, Kelsey Hawkins, Shaun Edwards, Stuart Glaser, Wim Meeussen 29 | * https://opensource.org/licenses/BSD-3-Clause 30 | 31 | ABB PC SDK 32 | * Copyright (c) 2021 ABB 33 | * https://developercenter.robotstudio.com/pc-sdk 34 | 35 | Convertalot 36 | * Copyright (c) 2004 Stephen R. Schmitt 37 | * http://www.convertalot.com/ 38 | 39 | Euclidean Space 40 | * Copyright (c) 1998-2021 Martin John Baker 41 | * http://www.euclideanspace.com/ 42 | -------------------------------------------------------------------------------- /Robots.slnx: -------------------------------------------------------------------------------- 1 | <Solution> 2 | <Project Path="build\Robots.Build\Robots.Build.csproj" /> 3 | <Project Path="src\Robots.Grasshopper\Robots.Grasshopper.csproj"> 4 | <BuildDependency Project="src\Robots\Robots.csproj" /> 5 | </Project> 6 | <Project Path="src\Robots\Robots.csproj" /> 7 | <Project Path="tests\Robots.Tests\Robots.Tests.csproj"> 8 | <BuildDependency Project="src\Robots\Robots.csproj" /> 9 | </Project> 10 | </Solution> -------------------------------------------------------------------------------- /build/Assets/Icons.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/build/Assets/Icons.ai -------------------------------------------------------------------------------- /build/Assets/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/build/Assets/icon128.png -------------------------------------------------------------------------------- /build/Assets/iconRhino128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/build/Assets/iconRhino128.png -------------------------------------------------------------------------------- /build/Assets/iconRobot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/build/Assets/iconRobot.png -------------------------------------------------------------------------------- /build/Robots.Build/Program.cs: -------------------------------------------------------------------------------- 1 | using RhinoPackager; 2 | using RhinoPackager.Commands; 3 | 4 | var app = App.Create(args); 5 | Props props = new("Directory.Build.props"); 6 | Github github = new("visose", "Robots"); 7 | 8 | app.Add( 9 | [ 10 | new Test 11 | ( 12 | testProject: "tests/Robots.Tests/Robots.Tests.csproj" 13 | ), 14 | new CheckVersion 15 | ( 16 | props: props, 17 | github: github 18 | ), 19 | new Build 20 | ( 21 | buildProject: "src/Robots.Grasshopper/Robots.Grasshopper.csproj" 22 | ), 23 | new Yak 24 | ( 25 | props: props, 26 | sourceFolder: "artifacts/bin/Robots.Grasshopper/release", 27 | files: 28 | [ 29 | "Robots.dll", 30 | "Robots.gha", 31 | "ABB.Robotics.Controllers.PC.dll", 32 | "RobotStudio.Services.RobApi.Desktop.dll", 33 | "RobotStudio.Services.RobApi.dll", 34 | "Renci.SshNet.dll", 35 | "iconRobot.png" 36 | ], 37 | tags: 38 | [ 39 | "rh7_0-any", 40 | "rh8_0-any" 41 | ] 42 | ), 43 | new Nuget 44 | ( 45 | props: props, 46 | project: "src/Robots/Robots.csproj", 47 | targets: "netstandard2.0" 48 | ), 49 | new Nuget 50 | ( 51 | props: props, 52 | project: "src/Robots.Grasshopper/Robots.Grasshopper.csproj", 53 | targets: "net48" 54 | ), 55 | new Release 56 | ( 57 | props: props, 58 | github: github, 59 | notesFile: "RELEASE", 60 | message: "> This **release** can only be installed through the package manager in **Rhino 7** or **Rhino 8** using the `_PackageManager` command.\n> Check the [readme](../../blob/master/.github/README.md) for more details." 61 | ) 62 | ]); 63 | 64 | await app.RunAsync(); 65 | -------------------------------------------------------------------------------- /build/Robots.Build/Robots.Build.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <OutputType>Exe</OutputType> 5 | <TargetFramework>net8.0</TargetFramework> 6 | <StartWorkingDirectory>$(RootDir)</StartWorkingDirectory> 7 | <StartArguments><!--debug--></StartArguments> 8 | <NoWarn>CA1852</NoWarn> 9 | </PropertyGroup> 10 | 11 | <ItemGroup> 12 | <PackageReference Include="RhinoPackager" Version="1.4.0" /> 13 | </ItemGroup> 14 | 15 | </Project> -------------------------------------------------------------------------------- /docs/Bartlett/Adhesive_extruder.3dm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/docs/Bartlett/Adhesive_extruder.3dm -------------------------------------------------------------------------------- /docs/Bartlett/Flange.3dm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/docs/Bartlett/Flange.3dm -------------------------------------------------------------------------------- /docs/Bartlett/IO_layout.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/docs/Bartlett/IO_layout.PNG -------------------------------------------------------------------------------- /docs/Bartlett/IO_layout.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/docs/Bartlett/IO_layout.pdf -------------------------------------------------------------------------------- /docs/Images/coordinate system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/docs/Images/coordinate system.png -------------------------------------------------------------------------------- /docs/Images/iconRobot.svg: -------------------------------------------------------------------------------- 1 | <svg xmlns="http://www.w3.org/2000/svg" width="80" height ="80" viewBox="0 0 30 30"> 2 | <g fill="#666" transform="translate(-2.4347 -3.222)"> 3 | <path d="M12.418 15.478c-.11848.49572-.23782.99038-.35975 1.4851-.38263 1.1293-1.4348 1.9502-2.6044 2.088 1.4812 1.1072 2.984 2.1888 4.4591 3.3033.96007.59176 1.7463 1.6178 2.9289 1.7416.3812.02938.76836-.0304 1.1193-.18352 1.4785-.57034 1.8722-2.7209.69637-3.7797-2.0554-1.5814-4.1542-3.1096-6.2393-4.6548z"/> 4 | <path d="M17.324 17.989c.0848.2738 1.0606.82502 1.4848 1.2097 1.7715 1.0723 1.8171 3.9533.11262 5.1092-1.109.86684-2.7507.80608-3.8492-.04541-.36988-.1549-.98772-.93496-1.167-.76038v3.501h-1.4207v2.6312h-2.901v3.522h15.588v-3.522h-3.0469v-2.6312h-1.315c.0023-1.9754-.0046-3.9522.0031-5.9264-.20336-1.7122-1.727-3.1696-3.4887-3.0878zm7.1199-12.235c.06656.75392-.16302 1.5326-.72312 2.0807-.55589.60126-1.396.91128-2.2095.83368-.06176-.0038-.12304-.01093-.18351-.01944l.65629 2.7625 4.7775 1.6067-3.7809-2.3444.63078-1.6589 1.2603-1.0415 1.5398-.13856 1.5958 3.8842-.63195-4.8857z"/> 5 | <path d="M21.739 7.8463c-.42927.00998-.85804-.14503-1.1765-.43428.26418-.2826.46792-.62316.58174-.99337.26055-.69384.17701-1.4875-.16367-2.139.23397-.10052.48942-.15182.74378-.15556.67735-.01617 1.3806.33355 1.6804.95926.34419.55787.2882 1.2949-.04538 1.8441-.3249.56362-.9581.96608-1.6204.91878z"/> 6 | <path d="M21.724 4.1238c-.25438.00374-.5086.05504-.74257.15556.34067.65145.42328 1.4454.16273 2.1393-.11383.37019-.31663.71124-.58081.99378.31843.28926.74736.4441 1.1766.43412.66237.0473 1.2953-.3557 1.6202-.91936.33357-.54916.38885-1.2855.04466-1.8434-.29981-.62575-1.0035-.97627-1.6808-.9601zm-10.059 3.732c-1.3997-.01957-2.3461-1.7463-1.5946-2.9316.44367-.8816 1.4945-1.0714 2.3889-1.038 2.103-.08678 4.2072-.2779 6.3095-.30045 1.3779.13815 2.1781 1.8937 1.3695 3.024-.51586.8621-1.5804.94325-2.4799.93545-1.9978.09924-3.9951.23154-5.9934.31068z"/> 7 | <a transform="translate(2.9712 -10.859) scale(2.3518)"> 8 | <path d="M2.5725 7.1707c-.31728 1.2932-.60172 2.5961-.90848 3.8923-.20391.56778.20774 1.2464.81391 1.3033.43874.05933.89218-.21142 1.0423-.62892.28614-1.1455.54054-2.3002.80822-3.451-.2966.00564-.59246.00114-.88625-.0186-.5483-.10715-.84704-.59627-.86972-1.0971z"/> 9 | </a> 10 | </g> 11 | </svg> 12 | -------------------------------------------------------------------------------- /docs/Images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/docs/Images/logo.png -------------------------------------------------------------------------------- /docs/Sponsors/Bmade_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/docs/Sponsors/Bmade_dark.png -------------------------------------------------------------------------------- /docs/Sponsors/Bmade_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/docs/Sponsors/Bmade_light.png -------------------------------------------------------------------------------- /lib/ABB.Robotics.Controllers.PC.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/lib/ABB.Robotics.Controllers.PC.dll -------------------------------------------------------------------------------- /lib/Newtonsoft.Json.Rhino.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/lib/Newtonsoft.Json.Rhino.dll -------------------------------------------------------------------------------- /lib/RobotStudio.Services.RobApi.Desktop.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/lib/RobotStudio.Services.RobApi.Desktop.dll -------------------------------------------------------------------------------- /lib/RobotStudio.Services.RobApi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/lib/RobotStudio.Services.RobApi.dll -------------------------------------------------------------------------------- /samples/Robots.Samples.Dynamo/Geometry.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.DesignScript.Runtime; 2 | using Rhino.Geometry; 3 | using D = Autodesk.DesignScript.Geometry; 4 | 5 | namespace Robots.Dynamo; 6 | 7 | [IsVisibleInDynamoLibrary(false)] 8 | public static class Geometry 9 | { 10 | public static D.Plane ToDPlane(this ref Plane p) 11 | { 12 | var origin = p.Origin.ToDPoint(); 13 | var xAxis = p.XAxis.ToDPoint(); 14 | var yAxis = p.YAxis.ToDPoint(); 15 | 16 | return D.Plane.ByOriginXAxisYAxis(origin, xAxis, yAxis); 17 | } 18 | 19 | public static Plane ToPlane(this D.Plane p) 20 | { 21 | var origin = p.Origin.ToPoint3d(); 22 | var xAxis = p.XAxis.ToVector3d(); 23 | var yAxis = p.YAxis.ToVector3d(); 24 | 25 | return new(origin, xAxis, yAxis); 26 | } 27 | 28 | static D.Point ToDPoint(this Point3d p) => D.Point.ByCoordinates(p.X, p.Y, p.Z); 29 | static D.Vector ToDPoint(this Vector3d p) => D.Vector.ByCoordinates(p.X, p.Y, p.Z); 30 | 31 | static Point3d ToPoint3d(this D.Point p) => new(p.X, p.Y, p.Z); 32 | static Vector3d ToVector3d(this D.Vector p) => new(p.X, p.Y, p.Z); 33 | } 34 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Dynamo/Program.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.DesignScript.Runtime; 2 | using Autodesk.DesignScript.Geometry; 3 | 4 | namespace Robots.Dynamo; 5 | 6 | public class Program : IDisposable 7 | { 8 | readonly Robots.Program _program; 9 | 10 | [IsVisibleInDynamoLibrary(false)] 11 | public Program(Robots.Program program) 12 | { 13 | program.MeshPoser = new DynamoMeshPoser(program.RobotSystem); 14 | _program = program; 15 | } 16 | 17 | [IsVisibleInDynamoLibrary(false)] 18 | public void Dispose() 19 | { 20 | var poser = _program.MeshPoser as IDisposable; 21 | poser?.Dispose(); 22 | } 23 | 24 | /// <summary> 25 | /// Run the robot simulation 26 | /// </summary> 27 | /// <param name="time">Normalized time (0 to 1)</param> 28 | /// <returns>Joint planes</returns> 29 | public List<Plane> Simulation(double time) 30 | { 31 | _program.Animate(time); 32 | var planes = _program.CurrentSimulationPose.Kinematics 33 | .SelectMany(k => k.Planes.Select(p => p.ToDPlane())); 34 | 35 | return planes.ToList(); 36 | } 37 | 38 | public override string ToString() => $"Program(Name = {_program.Name})"; 39 | } 40 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Dynamo/Robot.cs: -------------------------------------------------------------------------------- 1 | using Autodesk.DesignScript.Runtime; 2 | using Rhino.Geometry; 3 | 4 | namespace Robots.Dynamo; 5 | 6 | public class Robot 7 | { 8 | // static 9 | /// <summary> 10 | /// Load a robot system 11 | /// </summary> 12 | /// <param name="name">Name of robot system</param> 13 | /// <returns>Robot system</returns> 14 | public static Robot ByName(string name) 15 | { 16 | var system = FileIO.LoadRobotSystem(name, Plane.WorldXY); 17 | return new(system); 18 | } 19 | 20 | // instance 21 | [IsVisibleInDynamoLibrary(false)] 22 | public RobotSystem System { get; } 23 | 24 | private Robot(RobotSystem system) 25 | { 26 | System = system; 27 | } 28 | 29 | public override string ToString() => $"RobotSystem(Name = {System.Name})"; 30 | } 31 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Dynamo/Robots.Samples.Dynamo.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <AssemblyName>Robots.Dynamo</AssemblyName> 5 | <TargetFramework>net48</TargetFramework> 6 | <GenerateDocumentationFile>true</GenerateDocumentationFile> 7 | <NoWarn>CS1591</NoWarn> 8 | 9 | <RevitVersion>2023</RevitVersion> 10 | <DynamoVersion>2.13</DynamoVersion> 11 | 12 | <StartProgram>C:\Program Files\Autodesk\Revit $(RevitVersion)\Revit.exe</StartProgram> 13 | <StartArguments>/language ENG</StartArguments> 14 | <StartAction>Program</StartAction> 15 | </PropertyGroup> 16 | 17 | <ItemGroup> 18 | <Reference Include="PresentationCore" /> 19 | <Reference Include="PresentationFramework" /> 20 | <Reference Include="WindowsBase" /> 21 | <PackageReference Include="DynamoVisualProgramming.WpfUILibrary" Version="2.15.0.5383" ExcludeAssets="runtime" /> 22 | <PackageReference Include="DynamoVisualProgramming.ZeroTouchLibrary" Version="2.15.0.5383" ExcludeAssets="runtime" /> 23 | <PackageReference Include="HelixToolkit.Wpf.SharpDX" Version="2.17.0" ExcludeAssets="runtime" /> 24 | <PackageReference Include="Robots" Version="1.5.1" /> 25 | </ItemGroup> 26 | 27 | <Target Name="CopyPackage" AfterTargets="PostBuildEvent"> 28 | <ItemGroup> 29 | <BinFiles Include="$(TargetDir)\*" /> 30 | <PackageFiles Include="$(ProjectDir)package\**\*" /> 31 | </ItemGroup> 32 | 33 | <Copy SourceFiles="@(BinFiles)" DestinationFolder="$(AppData)\Dynamo\Dynamo Revit\$(DynamoVersion)\packages\$(AssemblyName)\bin" /> 34 | <Copy SourceFiles="@(PackageFiles)" DestinationFolder="$(AppData)\Dynamo\Dynamo Revit\$(DynamoVersion)\packages\$(AssemblyName)\%(RecursiveDir)" /> 35 | </Target> 36 | 37 | </Project> 38 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Dynamo/RobotsViewExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | using Autodesk.DesignScript.Runtime; 3 | using Dynamo.Wpf.Extensions; 4 | using Dynamo.Controls; 5 | using HelixToolkit.Wpf.SharpDX; 6 | 7 | namespace Robots.Dynamo; 8 | 9 | [IsVisibleInDynamoLibrary(false)] 10 | public class RobotsViewExtension : IViewExtension 11 | { 12 | internal static RobotsViewExtension Instance { get; private set; } = default!; 13 | 14 | Panel _content = default!; 15 | public string UniqueId => "073FBA9B-49C6-41D1-95FD-8335D6E8F305"; 16 | public string Name => nameof(RobotsViewExtension); 17 | 18 | public void Startup(ViewStartupParams viewStartupParams) { } 19 | 20 | public void Shutdown() { } 21 | 22 | public void Loaded(ViewLoadedParams viewLoadedParams) 23 | { 24 | var window = viewLoadedParams.DynamoWindow; 25 | _content = (Panel)window.Content; 26 | Instance = this; 27 | } 28 | 29 | Viewport3DX GetViewport() 30 | { 31 | Queue<object> queue = new(); 32 | 33 | foreach (var item in _content.Children) 34 | queue.Enqueue(item); 35 | 36 | while (queue.Any()) 37 | { 38 | var child = queue.Dequeue(); 39 | 40 | if (child is Watch3DView watch3Dview) 41 | return watch3Dview.View; 42 | 43 | if (child is Panel next) 44 | { 45 | foreach (var item in next.Children) 46 | queue.Enqueue(item); 47 | } 48 | } 49 | 50 | throw new InvalidOperationException("Could not find Viewport3DX"); 51 | } 52 | 53 | internal void AttachModels(List<MeshGeometryModel3D> models) 54 | { 55 | var viewport = GetViewport(); 56 | 57 | foreach (var model in models) 58 | viewport.Items.Add(model); 59 | } 60 | 61 | public void Dispose() { } 62 | } 63 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Dynamo/package/bin/Robots.Dynamo_DynamoCustomization.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0"?> 2 | <doc> 3 | <assembly> 4 | <name>Robots.Dynamo</name> 5 | </assembly> 6 | <namespaces> 7 | <namespace name="Robots.Dynamo"> 8 | <category>Robots</category> 9 | </namespace> 10 | </namespaces> 11 | </doc> -------------------------------------------------------------------------------- /samples/Robots.Samples.Dynamo/package/extra/Robots.Dynamo_ViewExtensionDefinition.xml: -------------------------------------------------------------------------------- 1 | <ViewExtensionDefinition> 2 | <AssemblyPath>..\bin\Robots.Dynamo.dll</AssemblyPath> 3 | <TypeName>Robots.Dynamo.RobotsViewExtension</TypeName> 4 | </ViewExtensionDefinition> -------------------------------------------------------------------------------- /samples/Robots.Samples.Dynamo/package/pkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "MIT", 3 | "file_hash": null, 4 | "name": "Robots for Dynamo", 5 | "version": "1.0.0", 6 | "description": "Robots for Dynamo", 7 | "group": "", 8 | "keywords": null, 9 | "dependencies": [], 10 | "contents": "", 11 | "engine_version": "2.13.0.0", 12 | "engine": "dynamo", 13 | "engine_metadata": "", 14 | "site_url": "https://github.com/visose/robots", 15 | "repository_url": "https://github.com/visose/Robots.git", 16 | "contains_binaries": true, 17 | "node_libraries": [ 18 | "Robots.Dynamo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 19 | ] 20 | } -------------------------------------------------------------------------------- /samples/Robots.Samples.Grasshopper/Python script example.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/samples/Robots.Samples.Grasshopper/Python script example.gh -------------------------------------------------------------------------------- /samples/Robots.Samples.Grasshopper/extrusion example.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/samples/Robots.Samples.Grasshopper/extrusion example.gh -------------------------------------------------------------------------------- /samples/Robots.Samples.Grasshopper/metal forming example.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/samples/Robots.Samples.Grasshopper/metal forming example.gh -------------------------------------------------------------------------------- /samples/Robots.Samples.Grasshopper/pick and place example.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/samples/Robots.Samples.Grasshopper/pick and place example.gh -------------------------------------------------------------------------------- /samples/Robots.Samples.Grasshopper/positioner example.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/samples/Robots.Samples.Grasshopper/positioner example.gh -------------------------------------------------------------------------------- /samples/Robots.Samples.Grasshopper/simple example.gh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/samples/Robots.Samples.Grasshopper/simple example.gh -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/.gitattributes: -------------------------------------------------------------------------------- 1 | # Collapse Unity-generated files on GitHub 2 | *.asset linguist-generated eol=lf 3 | *.mat linguist-generated 4 | *.meta linguist-generated 5 | *.prefab linguist-generated 6 | *.unity linguist-generated 7 | /Packages/packages-lock.json text eol=lf 8 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/.gitignore: -------------------------------------------------------------------------------- 1 | # Artifacts 2 | Library/ 3 | Temp/ 4 | obj/ 5 | Logs/ 6 | UserSettings/ 7 | 8 | *.sln 9 | *.csproj 10 | 11 | # Visual Studio 12 | .vs/ 13 | .vsconfig 14 | 15 | # Binaries 16 | /Assets/libs 17 | /Assets/libs.meta 18 | 19 | # Default settings 20 | ProjectSettings/AudioManager.asset 21 | ProjectSettings/CommonBurstAotSettings.json 22 | ProjectSettings/boot.config 23 | ProjectSettings/BurstAotSettings_StandaloneWindows.json 24 | ProjectSettings/ClusterInputManager.asset 25 | ProjectSettings/DynamicsManager.asset 26 | ProjectSettings/EditorBuildSettings.asset 27 | ProjectSettings/InputManager.asset 28 | ProjectSettings/MemorySettings.asset 29 | ProjectSettings/NavMeshAreas.asset 30 | ProjectSettings/Physics2DSettings.asset 31 | ProjectSettings/PresetManager.asset 32 | ProjectSettings/SceneTemplateSettings.json 33 | ProjectSettings/TagManager.asset 34 | ProjectSettings/TimeManager.asset 35 | ProjectSettings/UnityConnectSettings.asset 36 | ProjectSettings/VersionControlSettings.asset 37 | ProjectSettings/VFXManager.asset -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/CameraSimple.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.InputSystem; 3 | 4 | namespace Robots.Samples.Unity 5 | { 6 | public class CameraSimple : MonoBehaviour 7 | { 8 | Vector3 _target = new(0, 0.5f, 0); 9 | 10 | void Update() 11 | { 12 | var mouse = Mouse.current; 13 | var shouldRotate = mouse.rightButton.isPressed; 14 | 15 | if (shouldRotate) 16 | { 17 | var delta = mouse.delta.ReadValue() * 0.2f; 18 | 19 | transform.RotateAround(_target, Vector3.up, delta.x); 20 | transform.RotateAround(_target, transform.rotation * Vector3.right, -delta.y); 21 | } 22 | 23 | var scroll = mouse.scroll.ReadValue(); 24 | var shouldZoom = scroll.y != 0; 25 | 26 | if (shouldZoom) 27 | { 28 | float delta = Mathf.Sign(scroll.y) * 0.1f; 29 | float distance = (_target - transform.position).magnitude * delta; 30 | transform.Translate(Vector3.forward * distance, Space.Self); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/CameraSimple.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 236ae5210e79ea34aa022c1cd0334a11 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/Floor.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3473338ae247bc34fbcb137773691c14 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/Material.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1a0ed05928e15d440a26ef2c513c9f3d 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/Robot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using UnityEngine; 4 | 5 | namespace Robots.Samples.Unity 6 | { 7 | public class Robot : MonoBehaviour 8 | { 9 | [SerializeField] 10 | Material? _material; 11 | 12 | Program? _program; 13 | 14 | async void Start() 15 | { 16 | _program = await TestProgram.CreateAsync(); 17 | 18 | if (_material == null) 19 | throw new ArgumentNullException(nameof(_material)); 20 | 21 | _program.MeshPoser = new UnityMeshPoser(_program.RobotSystem, _material); 22 | } 23 | 24 | void Update() 25 | { 26 | if (_program is null) 27 | return; 28 | 29 | var time = Mathf.PingPong(Time.time, (float)_program.Duration); 30 | _program.Animate(time, false); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/Robot.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 60fb7ea14802f7641b80e3ec7b69343b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/Robots.Samples.Unity.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Robots.Samples.Unity", 3 | "rootNamespace": "", 4 | "references": [ 5 | "Unity.InputSystem" 6 | ], 7 | "includePlatforms": [ 8 | "Editor", 9 | "LinuxStandalone64", 10 | "macOSStandalone", 11 | "WindowsStandalone64" 12 | ], 13 | "excludePlatforms": [], 14 | "allowUnsafeCode": false, 15 | "overrideReferences": false, 16 | "precompiledReferences": [], 17 | "autoReferenced": true, 18 | "defineConstraints": [], 19 | "versionDefines": [], 20 | "noEngineReferences": false 21 | } -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/Robots.Samples.Unity.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: beffc0776581f5345b6ae59de82ddced 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/Scene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 99c9720ab356a0642a771bea13969a05 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/TestProgram.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace Robots.Samples.Unity 6 | { 7 | class TestProgram 8 | { 9 | public static async Task<Program> CreateAsync() 10 | { 11 | var robot = await GetRobotAsync(); 12 | 13 | var planeA = Plane.WorldYZ; 14 | var planeB = Plane.WorldYZ; 15 | planeA.Origin = new Point3d(300, 200, 610); 16 | planeB.Origin = new Point3d(300, -200, 610); 17 | var speed = new Speed(300); 18 | var targetA = new CartesianTarget(planeA, RobotConfigurations.Wrist, Motions.Joint); 19 | var targetB = new CartesianTarget(planeB, null, Motions.Linear, speed: speed); 20 | var toolpath = new SimpleToolpath() { targetA, targetB }; 21 | 22 | return new Program("TestProgram", robot, new[] { toolpath }); 23 | } 24 | 25 | static async Task<RobotSystem> GetRobotAsync() 26 | { 27 | var name = "Bartlett-IRB120"; 28 | 29 | try 30 | { 31 | return FileIO.LoadRobotSystem(name, Plane.WorldXY); 32 | } 33 | catch (ArgumentException e) 34 | { 35 | if (!e.Message.Contains("not found")) 36 | throw; 37 | 38 | UnityEngine.Debug.Log("Bartlett robot library not found, installing..."); 39 | await DownloadLibraryAsync(); 40 | return FileIO.LoadRobotSystem(name, Plane.WorldXY); 41 | } 42 | } 43 | 44 | static async Task DownloadLibraryAsync() 45 | { 46 | var online = new OnlineLibrary(); 47 | await online.UpdateLibraryAsync(); 48 | var bartlett = online.Libraries["Bartlett"]; 49 | await online.DownloadLibraryAsync(bartlett); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/TestProgram.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: be06aacbea90936418f5b6d8e5915c2f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/URP-Global.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 2ec995e51a6e251468d2a3fd8a686257, type: 3} 13 | m_Name: URP-Global 14 | m_EditorClassIdentifier: 15 | k_AssetVersion: 2 16 | lightLayerName0: Light Layer default 17 | lightLayerName1: Light Layer 1 18 | lightLayerName2: Light Layer 2 19 | lightLayerName3: Light Layer 3 20 | lightLayerName4: Light Layer 4 21 | lightLayerName5: Light Layer 5 22 | lightLayerName6: Light Layer 6 23 | lightLayerName7: Light Layer 7 24 | m_StripDebugVariants: 1 25 | m_StripUnusedPostProcessingVariants: 1 26 | m_StripUnusedVariants: 1 27 | supportRuntimeDebugDisplay: 0 28 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/URP-Global.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18dc0cd2c080841dea60987a38ce93fa 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/URP-Renderer.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c40be3174f62c4acf8c1216858c64956 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/URP.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} 13 | m_Name: URP 14 | m_EditorClassIdentifier: 15 | k_AssetVersion: 9 16 | k_AssetPreviousVersion: 9 17 | m_RendererType: 1 18 | m_RendererData: {fileID: 0} 19 | m_RendererDataList: 20 | - {fileID: 11400000, guid: c40be3174f62c4acf8c1216858c64956, type: 2} 21 | m_DefaultRendererIndex: 0 22 | m_RequireDepthTexture: 0 23 | m_RequireOpaqueTexture: 0 24 | m_OpaqueDownsampling: 1 25 | m_SupportsTerrainHoles: 0 26 | m_StoreActionsOptimization: 0 27 | m_SupportsHDR: 1 28 | m_MSAA: 4 29 | m_RenderScale: 1 30 | m_MainLightRenderingMode: 1 31 | m_MainLightShadowsSupported: 1 32 | m_MainLightShadowmapResolution: 4096 33 | m_AdditionalLightsRenderingMode: 1 34 | m_AdditionalLightsPerObjectLimit: 8 35 | m_AdditionalLightShadowsSupported: 1 36 | m_AdditionalLightsShadowmapResolution: 4096 37 | m_AdditionalLightsShadowResolutionTierLow: 128 38 | m_AdditionalLightsShadowResolutionTierMedium: 256 39 | m_AdditionalLightsShadowResolutionTierHigh: 512 40 | m_ReflectionProbeBlending: 1 41 | m_ReflectionProbeBoxProjection: 1 42 | m_ShadowDistance: 5 43 | m_ShadowCascadeCount: 4 44 | m_Cascade2Split: 0.25 45 | m_Cascade3Split: {x: 0.1, y: 0.3} 46 | m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} 47 | m_CascadeBorder: 0.1 48 | m_ShadowDepthBias: 1 49 | m_ShadowNormalBias: 1 50 | m_SoftShadowsSupported: 1 51 | m_ConservativeEnclosingSphere: 0 52 | m_NumIterationsEnclosingSphere: 64 53 | m_AdditionalLightsCookieResolution: 4096 54 | m_AdditionalLightsCookieFormat: 4 55 | m_UseSRPBatcher: 1 56 | m_SupportsDynamicBatching: 0 57 | m_MixedLightingSupported: 1 58 | m_SupportsLightLayers: 0 59 | m_DebugLevel: 0 60 | m_UseAdaptivePerformance: 1 61 | m_ColorGradingMode: 1 62 | m_ColorGradingLutSize: 32 63 | m_UseFastSRGBLinearConversion: 0 64 | m_ShadowType: 1 65 | m_LocalShadowsSupported: 0 66 | m_LocalShadowsAtlasResolution: 256 67 | m_MaxPixelLights: 0 68 | m_ShadowAtlasResolution: 256 69 | m_ShaderVariantLogLevel: 0 70 | m_VolumeFrameworkUpdateMode: 0 71 | m_ShadowCascades: 1 72 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/URP.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7b7fd9122c28c4d15b667c7040e3b3fd 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/UnityMeshPoser.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 274b97fc3bf7fa244afa5ab4fb37a048 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/Volume.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6560a915ef98420e9faacc1c7438823 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/csc.rsp: -------------------------------------------------------------------------------- 1 | -nullable -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Assets/csc.rsp.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4a4bf96f41eb0784dbef3f682bd29ef3 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.ide.visualstudio": "2.0.14", 4 | "com.unity.inputsystem": "1.3.0", 5 | "com.unity.render-pipelines.universal": "12.1.4", 6 | "org.nuget.robots": "1.1.10" 7 | }, 8 | "scopedRegistries": [ 9 | { 10 | "name": "Unity NuGet", 11 | "url": "https://unitynuget-registry.azurewebsites.net", 12 | "scopes": [ 13 | "org.nuget" 14 | ] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 11 7 | m_SerializationMode: 2 8 | m_LineEndingsForNewScripts: 2 9 | m_DefaultBehaviorMode: 0 10 | m_PrefabRegularEnvironment: {fileID: 0} 11 | m_PrefabUIEnvironment: {fileID: 0} 12 | m_SpritePackerMode: 0 13 | m_SpritePackerPaddingPower: 1 14 | m_Bc7TextureCompressor: 0 15 | m_EtcTextureCompressorBehavior: 1 16 | m_EtcTextureFastCompressor: 1 17 | m_EtcTextureNormalCompressor: 2 18 | m_EtcTextureBestCompressor: 4 19 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;asmref;rsp 20 | m_ProjectGenerationRootNamespace: 21 | m_EnableTextureStreamingInEditMode: 1 22 | m_EnableTextureStreamingInPlayMode: 1 23 | m_AsyncShaderCompilation: 1 24 | m_CachingShaderPreprocessor: 1 25 | m_PrefabModeAllowAutoSave: 1 26 | m_EnterPlayModeOptionsEnabled: 1 27 | m_EnterPlayModeOptions: 3 28 | m_GameObjectNamingDigits: 1 29 | m_GameObjectNamingScheme: 0 30 | m_AssetNamingUsesSpace: 1 31 | m_UseLegacyProbeSampleCount: 0 32 | m_SerializeInlineMappingsOnOneLine: 0 33 | m_DisableCookiesInLightmapper: 1 34 | m_AssetPipelineMode: 1 35 | m_RefreshImportMode: 0 36 | m_CacheServerMode: 0 37 | m_CacheServerEndpoint: 38 | m_CacheServerNamespacePrefix: default 39 | m_CacheServerEnableDownload: 1 40 | m_CacheServerEnableUpload: 1 41 | m_CacheServerEnableAuth: 0 42 | m_CacheServerEnableTls: 0 43 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/ProjectSettings/PackageManagerSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &1 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 61 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} 13 | m_Name: 14 | m_EditorClassIdentifier: 15 | m_EnablePreReleasePackages: 0 16 | m_EnablePackageDependencies: 1 17 | m_AdvancedSettingsExpanded: 1 18 | m_ScopedRegistriesSettingsExpanded: 1 19 | m_SeeAllPackageVersions: 0 20 | oneTimeWarningShown: 0 21 | m_Registries: 22 | - m_Id: main 23 | m_Name: 24 | m_Url: https://packages.unity.com 25 | m_Scopes: [] 26 | m_IsDefault: 1 27 | m_Capabilities: 7 28 | - m_Id: scoped:Unity NuGet 29 | m_Name: Unity NuGet 30 | m_Url: https://unitynuget-registry.azurewebsites.net 31 | m_Scopes: 32 | - org.nuget 33 | m_IsDefault: 0 34 | m_Capabilities: 0 35 | m_UserSelectedRegistryName: Unity NuGet 36 | m_UserAddingNewScopedRegistry: 0 37 | m_RegistryInfoDraft: 38 | m_Modified: 0 39 | m_ErrorMessage: 40 | m_UserModificationsInstanceId: -824 41 | m_OriginalInstanceId: -826 42 | m_LoadAssets: 0 43 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2021.2.10f1 2 | m_EditorVersionWithRevision: 2021.2.10f1 (ee872746220e) 3 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 0 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: High Fidelity 11 | pixelLightCount: 2 12 | shadows: 2 13 | shadowResolution: 1 14 | shadowProjection: 1 15 | shadowCascades: 2 16 | shadowDistance: 40 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 1 21 | skinWeights: 255 22 | textureQuality: 0 23 | anisotropicTextures: 2 24 | antiAliasing: 4 25 | softParticles: 0 26 | softVegetation: 1 27 | realtimeReflectionProbes: 1 28 | billboardsFaceCameraPosition: 1 29 | vSyncCount: 1 30 | lodBias: 2 31 | maximumLODLevel: 0 32 | streamingMipmapsActive: 0 33 | streamingMipmapsAddAllCameras: 1 34 | streamingMipmapsMemoryBudget: 512 35 | streamingMipmapsRenderersPerFrame: 512 36 | streamingMipmapsMaxLevelReduction: 2 37 | streamingMipmapsMaxFileIORequests: 1024 38 | particleRaycastBudget: 2048 39 | asyncUploadTimeSlice: 2 40 | asyncUploadBufferSize: 16 41 | asyncUploadPersistentBuffer: 1 42 | resolutionScalingFixedDPIFactor: 1 43 | customRenderPipeline: {fileID: 11400000, guid: 7b7fd9122c28c4d15b667c7040e3b3fd, 44 | type: 2} 45 | excludedTargetPlatforms: [] 46 | m_PerPlatformDefaultQuality: 47 | Android: 0 48 | CloudRendering: 0 49 | Lumin: 0 50 | Nintendo Switch: 0 51 | PS4: 0 52 | Server: 0 53 | Stadia: 0 54 | Standalone: 0 55 | WebGL: 0 56 | Windows Store Apps: 0 57 | XboxOne: 0 58 | iPhone: 0 59 | tvOS: 0 60 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/ProjectSettings/ShaderGraphSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &1 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 61 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: de02f9e1d18f588468e474319d09a723, type: 3} 13 | m_Name: 14 | m_EditorClassIdentifier: 15 | customInterpolatorErrorThreshold: 32 16 | customInterpolatorWarningThreshold: 16 17 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/ProjectSettings/URPProjectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &1 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 61 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3} 13 | m_Name: 14 | m_EditorClassIdentifier: 15 | m_LastMaterialVersion: 5 16 | -------------------------------------------------------------------------------- /samples/Robots.Samples.Unity/README.md: -------------------------------------------------------------------------------- 1 | # Running the Unity project 2 | 3 | This sample works in Unity 2021.2.10f1, and requires no further steps to work after cloning. The *Robots* and *Rhino3dm* NuGet packages are distributed via this package registry: https://github.com/xoofx/UnityNuGet. -------------------------------------------------------------------------------- /samples/Robots.Samples.Wpf/App.xaml: -------------------------------------------------------------------------------- 1 | <Application x:Class="Robots.Samples.Wpf.App" 2 | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 | StartupUri="MainWindow.xaml"> 5 | <Application.Resources> 6 | </Application.Resources> 7 | </Application> -------------------------------------------------------------------------------- /samples/Robots.Samples.Wpf/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace Robots.Samples.Wpf; 4 | 5 | partial class App : Application 6 | { 7 | } -------------------------------------------------------------------------------- /samples/Robots.Samples.Wpf/Robots.Samples.Wpf.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>net6.0-windows</TargetFramework> 5 | <OutputType>WinExe</OutputType> 6 | <UseWPF>true</UseWPF> 7 | </PropertyGroup> 8 | 9 | <ItemGroup> 10 | <PackageReference Include="HelixToolkit.SharpDX.Core.Wpf" Version="2.20.2" /> 11 | <PackageReference Include="SharpDX.Mathematics" Version="4.2.0" /> 12 | <PackageReference Include="Robots" Version="1.1.5"/> 13 | </ItemGroup> 14 | 15 | </Project> -------------------------------------------------------------------------------- /samples/Robots.Samples.Wpf/TestProgram.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using Plane = Rhino.Geometry.Plane; 3 | 4 | namespace Robots.Samples.Wpf; 5 | 6 | class TestProgram 7 | { 8 | public static async Task<Program> CreateAsync() 9 | { 10 | var robot = await GetRobotAsync(); 11 | 12 | var planeA = Plane.WorldYZ; 13 | var planeB = Plane.WorldYZ; 14 | planeA.Origin = new Point3d(300, 200, 610); 15 | planeB.Origin = new Point3d(300, -200, 610); 16 | var speed = new Speed(300); 17 | var targetA = new CartesianTarget(planeA, RobotConfigurations.Wrist, Motions.Joint); 18 | var targetB = new CartesianTarget(planeB, null, Motions.Linear, speed: speed); 19 | var toolpath = new SimpleToolpath() { targetA, targetB }; 20 | 21 | return new Program("TestProgram", robot, new[] { toolpath }); 22 | } 23 | 24 | static async Task<RobotSystem> GetRobotAsync() 25 | { 26 | var name = "Bartlett-IRB120"; 27 | 28 | try 29 | { 30 | return FileIO.LoadRobotSystem(name, Plane.WorldXY); 31 | } 32 | catch (ArgumentException e) 33 | { 34 | if (!e.Message.Contains("not found")) 35 | throw; 36 | 37 | await DownloadLibraryAsync(); 38 | return FileIO.LoadRobotSystem(name, Plane.WorldXY); 39 | } 40 | } 41 | 42 | static async Task DownloadLibraryAsync() 43 | { 44 | var online = new OnlineLibrary(); 45 | await online.UpdateLibraryAsync(); 46 | var bartlett = online.Libraries["Bartlett"]; 47 | await online.DownloadLibraryAsync(bartlett); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconAngles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconAngles.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconCheckCollisions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconCheckCollisions.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconCommandParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconCommandParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconCreateFrame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconCreateFrame.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconCreateProgram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconCreateProgram.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconCreateTarget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconCreateTarget.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconCreateTool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconCreateTool.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconCustomCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconCustomCode.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconCustomCommand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconCustomCommand.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconDeconstructProgramTarget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconDeconstructProgramTarget.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconDeconstructTarget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconDeconstructTarget.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconDeconstructToolpath.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconDeconstructToolpath.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconFrame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconFrame.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconFrameParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconFrameParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconGetPlane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconGetPlane.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconGroupCommand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconGroupCommand.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconJointsParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconJointsParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconKinematics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconKinematics.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconMessage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconMessage.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconPostProcessorParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconPostProcessorParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconProgramParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconProgramParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconPulseDO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconPulseDO.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconRobot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconRobot.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconRobotParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconRobotParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconSave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconSave.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconSetAO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconSetAO.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconSetDO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconSetDO.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconSimpleTrail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconSimpleTrail.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconSimulation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconSimulation.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconSpeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconSpeed.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconSpeedParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconSpeedParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconStopCommand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconStopCommand.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconTargetParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconTargetParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconToPlane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconToPlane.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconTool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconTool.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconToolParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconToolParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconToolpathParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconToolpathParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconURRemote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconURRemote.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconWait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconWait.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconWaitDI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconWaitDI.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Assets/Embed/iconZoneParam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots.Grasshopper/Assets/Embed/iconZoneParam.png -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Commands/CustomCommand.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper.Commands; 2 | 3 | public class CustomCommand : GH_Component 4 | { 5 | public CustomCommand() : base("Custom command", "CustomCmd", "Custom command written in the manufacturer specific language", "Robots", "Commands") { } 6 | public override GH_Exposure Exposure => GH_Exposure.primary; 7 | public override Guid ComponentGuid => new("{713A6DF0-6C73-477F-8CA5-2FE18F3DE7C4}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconCustomCommand"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddTextParameter("Name", "N", "Name", GH_ParamAccess.item, "CustomCommand"); 13 | pManager.AddTextParameter("Manufacturer", "M", "Robot manufacturer, options: ABB, KUKA, UR, Staubli, FrankaEmika, Doosan, Fanuc, Igus, Jaka, Other, All. If you select 'All', the command will always be included irrespective of the manufacturer.", GH_ParamAccess.item, "All"); 14 | pManager.AddTextParameter("Code", "C", "Command code", GH_ParamAccess.item); 15 | pManager.AddTextParameter("Declaration", "D", "Variable declaration and assignment", GH_ParamAccess.item); 16 | pManager[2].Optional = true; 17 | pManager[3].Optional = true; 18 | } 19 | 20 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 21 | { 22 | pManager.AddParameter(new CommandParameter(), "Command", "C", "Command", GH_ParamAccess.item); 23 | } 24 | 25 | protected override void SolveInstance(IGH_DataAccess DA) 26 | { 27 | string? name = null; 28 | string? manufacturerText = null; 29 | string? code = null, declaration = null; 30 | 31 | if (!DA.GetData(0, ref name) || name is null) return; 32 | if (!DA.GetData(1, ref manufacturerText) || manufacturerText is null) return; 33 | DA.GetData(2, ref code); 34 | DA.GetData(3, ref declaration); 35 | 36 | var command = new Robots.Commands.Custom(name); 37 | 38 | if (!Enum.TryParse<Manufacturers>(manufacturerText, out var manufacturer)) 39 | { 40 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $" Manufacturer '{manufacturerText}' not valid."); 41 | return; 42 | } 43 | 44 | command.AddCommand(manufacturer, code, declaration); 45 | DA.SetData(0, command); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Commands/Group.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper.Commands; 2 | 3 | public class Group : GH_Component 4 | { 5 | public Group() : base("Group command", "GroupCmd", "Group of commands", "Robots", "Commands") { } 6 | public override GH_Exposure Exposure => GH_Exposure.primary; 7 | public override Guid ComponentGuid => new("{17485955-818B-4D0E-9986-26264E1F86DC}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconGroupCommand"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddParameter(new CommandParameter(), "Commands", "C", "Group of commands", GH_ParamAccess.list); 13 | } 14 | 15 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 16 | { 17 | pManager.AddParameter(new CommandParameter(), "Command", "C", "Command", GH_ParamAccess.item); 18 | } 19 | 20 | protected override void SolveInstance(IGH_DataAccess DA) 21 | { 22 | var commands = new List<GH_Command>(); 23 | 24 | if (!DA.GetDataList(0, commands)) return; 25 | 26 | var command = new Robots.Commands.Group(); 27 | command.AddRange(commands.Select(x => x.Value)); 28 | DA.SetData(0, command); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Commands/Message.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper.Commands; 2 | 3 | public class Message : GH_Component 4 | { 5 | public Message() : base("Message", "Message", "Sends a text message to the teach pendant", "Robots", "Commands") { } 6 | public override GH_Exposure Exposure => GH_Exposure.secondary; 7 | public override Guid ComponentGuid => new("{CFAABB24-CAEE-49FC-850F-BE9F70F070CA}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconMessage"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddTextParameter("Message", "M", "Message to display in teach pendant", GH_ParamAccess.item); 13 | } 14 | 15 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 16 | { 17 | pManager.AddParameter(new CommandParameter(), "Command", "C", "Command", GH_ParamAccess.item); 18 | } 19 | 20 | protected override void SolveInstance(IGH_DataAccess DA) 21 | { 22 | string message = string.Empty; 23 | 24 | if (!DA.GetData(0, ref message)) return; 25 | 26 | var command = new Robots.Commands.Message(message); 27 | DA.SetData(0, command); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Commands/PulseDO.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper.Commands; 2 | 3 | public class PulseDO : GH_Component 4 | { 5 | public PulseDO() : base("Pulse DO", "PulseDO", "Send a pulse to a digital output", "Robots", "Commands") { } 6 | public override GH_Exposure Exposure => GH_Exposure.secondary; 7 | public override Guid ComponentGuid => new("{3CBDCD59-9621-4A0F-86BF-F4CC876E360D}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconPulseDO"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddIntegerParameter("DO", "D", "Digital output number", GH_ParamAccess.item); 13 | pManager.AddNumberParameter("Time", "T", "Duration of pulse", GH_ParamAccess.item, 0.2); 14 | } 15 | 16 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 17 | { 18 | pManager.AddParameter(new CommandParameter(), "Command", "C", "Command", GH_ParamAccess.item); 19 | } 20 | 21 | protected override void SolveInstance(IGH_DataAccess DA) 22 | { 23 | int DO = 0; 24 | double length = 0; 25 | 26 | if (!DA.GetData(0, ref DO)) return; 27 | if (!DA.GetData(1, ref length)) return; 28 | 29 | var command = new Robots.Commands.PulseDO(DO, length); 30 | DA.SetData(0, command); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Commands/SetAO.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper.Commands; 2 | 3 | public class SetAO : GH_Component 4 | { 5 | public SetAO() : base("Set AO", "SetAO", "Set analog output", "Robots", "Commands") { } 6 | public override GH_Exposure Exposure => GH_Exposure.secondary; 7 | public override Guid ComponentGuid => new("{CAA1A764-D588-4D63-95EA-9C8D43374B8D}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconSetAO"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddIntegerParameter("AO", "A", "Analog output number", GH_ParamAccess.item); 13 | pManager.AddNumberParameter("Value", "V", "Analog output value", GH_ParamAccess.item); 14 | } 15 | 16 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 17 | { 18 | pManager.AddParameter(new CommandParameter(), "Command", "C", "Command", GH_ParamAccess.item); 19 | } 20 | 21 | protected override void SolveInstance(IGH_DataAccess DA) 22 | { 23 | int AO = 0; 24 | double value = 0; 25 | 26 | if (!DA.GetData(0, ref AO)) return; 27 | if (!DA.GetData(1, ref value)) return; 28 | 29 | var command = new Robots.Commands.SetAO(AO, value); 30 | DA.SetData(0, command); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Commands/SetDO.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper.Commands; 2 | 3 | public class SetDO : GH_Component 4 | { 5 | public SetDO() : base("Set DO", "SetDO", "Set digital output", "Robots", "Commands") { } 6 | public override GH_Exposure Exposure => GH_Exposure.secondary; 7 | public override Guid ComponentGuid => new("{C2F263E3-BF97-4E48-B2CB-42D3A5FE6190}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconSetDO"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddIntegerParameter("DO", "D", "Digital output number", GH_ParamAccess.item); 13 | pManager.AddBooleanParameter("Value", "V", "Digital output value", GH_ParamAccess.item); 14 | } 15 | 16 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 17 | { 18 | pManager.AddParameter(new CommandParameter(), "Command", "C", "Command", GH_ParamAccess.item); 19 | } 20 | 21 | protected override void SolveInstance(IGH_DataAccess DA) 22 | { 23 | int DO = 0; 24 | bool value = false; 25 | 26 | if (!DA.GetData(0, ref DO)) return; 27 | if (!DA.GetData(1, ref value)) return; 28 | 29 | var command = new Robots.Commands.SetDO(DO, value); 30 | DA.SetData(0, command); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Commands/Stop.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper.Commands; 2 | 3 | public class Stop : GH_Component 4 | { 5 | public Stop() : base("Stop program", "Stop", "Stops the program until an operator starts it again", "Robots", "Commands") { } 6 | public override GH_Exposure Exposure => GH_Exposure.secondary; 7 | public override Guid ComponentGuid => new("{80E4E1AD-D1C0-441F-BDC5-5E810BCECE61}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconStopCommand"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | } 13 | 14 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 15 | { 16 | pManager.AddParameter(new CommandParameter(), "Command", "C", "Command", GH_ParamAccess.item); 17 | } 18 | 19 | protected override void SolveInstance(IGH_DataAccess DA) 20 | { 21 | var command = new Robots.Commands.Stop(); 22 | DA.SetData(0, command); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Commands/Wait.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper.Commands; 2 | 3 | public class Wait : GH_Component 4 | { 5 | public Wait() : base("Wait", "Wait", "Stops the program for a specific amount of time", "Robots", "Commands") { } 6 | public override GH_Exposure Exposure => GH_Exposure.secondary; 7 | public override Guid ComponentGuid => new("{5E7BA355-7EAC-4A5D-B736-286043AB0A45}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconWait"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddNumberParameter("Time", "T", "Time in seconds", GH_ParamAccess.item); 13 | } 14 | 15 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 16 | { 17 | pManager.AddParameter(new CommandParameter(), "Command", "C", "Command", GH_ParamAccess.item); 18 | } 19 | 20 | protected override void SolveInstance(IGH_DataAccess DA) 21 | { 22 | double time = 0; 23 | 24 | if (!DA.GetData(0, ref time)) return; 25 | 26 | var command = new Robots.Commands.Wait(time); 27 | DA.SetData(0, command); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Commands/WaitDI.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper.Commands; 2 | 3 | public class WaitDI : GH_Component 4 | { 5 | public WaitDI() : base("Wait DI", "WaitDI", "Stops the program until a digital input is turned on", "Robots", "Commands") { } 6 | public override GH_Exposure Exposure => GH_Exposure.secondary; 7 | public override Guid ComponentGuid => new("{8A930C8F-3BCE-4476-9E30-3F5C23DB2FB9}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconWaitDI"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddIntegerParameter("DI", "D", "Digital input number", GH_ParamAccess.item); 13 | } 14 | 15 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 16 | { 17 | pManager.AddParameter(new CommandParameter(), "Command", "C", "Command", GH_ParamAccess.item); 18 | } 19 | 20 | protected override void SolveInstance(IGH_DataAccess DA) 21 | { 22 | int DI = 0; 23 | 24 | if (!DA.GetData(0, ref DI)) return; 25 | 26 | var command = new Robots.Commands.WaitDI(DI); 27 | DA.SetData(0, command); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/ComponentForm.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Eto.Drawing; 3 | using Eto.Forms; 4 | 5 | namespace Robots.Grasshopper; 6 | 7 | class ComponentForm : Form 8 | { 9 | public ComponentForm() 10 | { 11 | Maximizable = false; 12 | Minimizable = false; 13 | Resizable = false; 14 | Topmost = true; 15 | ShowInTaskbar = true; 16 | Owner = Rhino.UI.RhinoEtoApp.MainWindow; 17 | } 18 | 19 | public override bool Visible 20 | { 21 | get => base.Visible; 22 | set 23 | { 24 | if (value) 25 | CenterOnMouse(); 26 | 27 | base.Visible = value; 28 | } 29 | } 30 | 31 | void CenterOnMouse() 32 | { 33 | var mousePos = Mouse.Position; 34 | int x = (int)mousePos.X + 20; 35 | int y = (int)mousePos.Y - MinimumSize.Height / 2; 36 | Location = new Point(x, y); 37 | } 38 | 39 | protected override void OnClosing(CancelEventArgs e) 40 | { 41 | Visible = false; 42 | e.Cancel = true; 43 | 44 | base.OnClosing(e); 45 | } 46 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_Command.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel.Types; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class GH_Command : GH_Goo<Command> 6 | { 7 | public GH_Command() { Value = Command.Default; } 8 | public GH_Command(GH_Command goo) { Value = goo.Value; } 9 | public GH_Command(Command native) { Value = native; } 10 | public override IGH_Goo Duplicate() => new GH_Command(this); 11 | public override bool IsValid => true; 12 | public override string TypeName => "Command"; 13 | public override string TypeDescription => "Command"; 14 | public override string ToString() => Value.ToString(); 15 | 16 | public override bool CastFrom(object source) 17 | { 18 | switch (source) 19 | { 20 | case Command command: 21 | Value = command; 22 | return true; 23 | default: 24 | return false; 25 | } 26 | } 27 | 28 | public override bool CastTo<Q>(ref Q target) 29 | { 30 | if (typeof(Q).IsAssignableFrom(typeof(Command))) 31 | { 32 | target = (Q)(object)Value; 33 | return true; 34 | } 35 | 36 | return false; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_Frame.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using Grasshopper.Kernel.Types; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class GH_Frame : GH_Goo<Frame> 7 | { 8 | public GH_Frame() { Value = Frame.Default; } 9 | public GH_Frame(GH_Frame goo) { Value = goo.Value; } 10 | public GH_Frame(Frame native) { Value = native; } 11 | public override IGH_Goo Duplicate() => new GH_Frame(this); 12 | public override bool IsValid => true; 13 | public override string TypeName => "Frame"; 14 | public override string TypeDescription => "Frame"; 15 | public override string ToString() => Value.ToString(); 16 | 17 | public override bool CastFrom(object source) 18 | { 19 | switch (source) 20 | { 21 | case Frame frame: 22 | Value = frame; 23 | return true; 24 | case GH_Plane plane: 25 | Value = new Frame(plane.Value); 26 | return true; 27 | case GH_Point point: 28 | Value = new Frame(new Plane(point.Value, Vector3d.XAxis, Vector3d.YAxis)); 29 | return true; 30 | default: 31 | return false; 32 | } 33 | } 34 | 35 | public override bool CastTo<Q>(ref Q target) 36 | { 37 | if (typeof(Q).IsAssignableFrom(typeof(Frame))) 38 | { 39 | target = (Q)(object)Value; 40 | return true; 41 | } 42 | 43 | if (typeof(Q) == typeof(GH_Plane)) 44 | { 45 | target = (Q)(object)new GH_Plane(Value.Plane); 46 | return true; 47 | } 48 | 49 | return false; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_Joints.cs: -------------------------------------------------------------------------------- 1 | using GH_IO.Serialization; 2 | using Grasshopper.Kernel.Types; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class GH_Joints : GH_Goo<double[]> 7 | { 8 | public GH_Joints() { Value = []; } 9 | public GH_Joints(GH_Joints goo) { Value = goo.Value; } 10 | public GH_Joints(double[] native) { Value = native; } 11 | public override IGH_Goo Duplicate() => new GH_Joints(this); 12 | public override bool IsValid => true; 13 | public override string TypeName => "Joints"; 14 | public override string TypeDescription => "Joints"; 15 | public override string ToString() => string.Join(",", Value.Select(x => $"{x:0.#####}")); 16 | 17 | public override bool CastFrom(object source) 18 | { 19 | switch (source) 20 | { 21 | case GH_Number number: 22 | Value = [number.Value]; 23 | return true; 24 | case GH_Integer integer: 25 | Value = [(double)integer.Value]; 26 | return true; 27 | case GH_String text: 28 | { 29 | if (string.IsNullOrWhiteSpace(text.Value)) 30 | { 31 | Value = []; 32 | return true; 33 | } 34 | 35 | string[] texts = text.Value.Split(','); 36 | double[] values = new double[texts.Length]; 37 | 38 | for (int i = 0; i < texts.Length; i++) 39 | { 40 | if (!GH_Convert.ToDouble_Secondary(texts[i], ref values[i])) 41 | return false; 42 | } 43 | 44 | Value = values; 45 | return true; 46 | } 47 | } 48 | 49 | return false; 50 | } 51 | 52 | public override bool CastTo<Q>(ref Q target) 53 | { 54 | if (typeof(Q).IsAssignableFrom(typeof(double[]))) 55 | { 56 | target = (Q)(object)Value; 57 | return true; 58 | } 59 | 60 | return false; 61 | } 62 | 63 | public override bool Write(GH_IWriter writer) 64 | { 65 | writer.SetDoubleArray("Value", Value); 66 | return true; 67 | } 68 | 69 | public override bool Read(GH_IReader reader) 70 | { 71 | Value = reader.GetDoubleArray("Value"); 72 | return true; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_PostProcessor.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel.Types; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class GH_PostProcessor : GH_Goo<IPostProcessor> 6 | { 7 | public GH_PostProcessor() { Value = null!; } 8 | public GH_PostProcessor(IPostProcessor native) { Value = native; } 9 | public override IGH_Goo Duplicate() => new GH_PostProcessor(Value); 10 | public override bool IsValid => true; 11 | public override string TypeName => "PostProcessor"; 12 | public override string TypeDescription => "PostProcessor"; 13 | public override string ToString() => "PostProcessor" + (Value is null ? "" : $"({Value.GetType().Name})"); 14 | 15 | public override bool CastFrom(object source) 16 | { 17 | switch (source) 18 | { 19 | case IPostProcessor post: 20 | Value = post; 21 | return true; 22 | default: 23 | return false; 24 | } 25 | } 26 | 27 | public override bool CastTo<Q>(ref Q target) 28 | { 29 | if (typeof(Q).IsAssignableFrom(typeof(IPostProcessor))) 30 | { 31 | target = (Q)(object)Value; 32 | return true; 33 | } 34 | 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_Program.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel.Types; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class GH_Program : GH_Goo<IProgram> 6 | { 7 | public GH_Program() { } 8 | public GH_Program(GH_Program goo) { Value = goo.Value; } 9 | public GH_Program(IProgram native) { Value = native; } 10 | public override IGH_Goo Duplicate() => new GH_Program(this); 11 | public override bool IsValid => true; 12 | public override string TypeName => "Program"; 13 | public override string TypeDescription => "Program"; 14 | public override string ToString() => Value.ToString(); 15 | 16 | public override bool CastFrom(object source) 17 | { 18 | switch (source) 19 | { 20 | case IProgram program: 21 | Value = program; 22 | return true; 23 | default: 24 | return false; 25 | } 26 | } 27 | 28 | public override bool CastTo<Q>(ref Q target) 29 | { 30 | if (typeof(Q).IsAssignableFrom(typeof(IProgram))) 31 | { 32 | target = (Q)Value; 33 | return true; 34 | } 35 | 36 | return false; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_RobotSystem.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using Grasshopper.Kernel.Types; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class GH_RobotSystem : GH_Goo<RobotSystem>, IGH_PreviewData 7 | { 8 | public GH_RobotSystem() { } 9 | public GH_RobotSystem(GH_RobotSystem goo) { Value = goo.Value; } 10 | public GH_RobotSystem(RobotSystem native) { Value = native; } 11 | public override IGH_Goo Duplicate() => new GH_RobotSystem(this); 12 | public override bool IsValid => true; 13 | public override string TypeName => "RobotSystem"; 14 | public override string TypeDescription => "RobotSystem"; 15 | public override string ToString() => Value.ToString(); 16 | 17 | public override bool CastFrom(object source) 18 | { 19 | switch (source) 20 | { 21 | case RobotSystem system: 22 | Value = system; 23 | return true; 24 | default: 25 | return false; 26 | } 27 | } 28 | 29 | public override bool CastTo<Q>(ref Q target) 30 | { 31 | if (typeof(Q).IsAssignableFrom(typeof(RobotSystem))) 32 | { 33 | target = (Q)(object)Value; 34 | return true; 35 | } 36 | 37 | return false; 38 | } 39 | 40 | public BoundingBox ClippingBox => Value.DisplayMesh.GetBoundingBox(true); 41 | 42 | public void DrawViewportMeshes(GH_PreviewMeshArgs args) 43 | { 44 | args.Pipeline.DrawMeshShaded(Value.DisplayMesh, args.Material); 45 | } 46 | 47 | public void DrawViewportWires(GH_PreviewWireArgs args) 48 | { 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_Speed.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel.Types; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class GH_Speed : GH_Goo<Speed> 6 | { 7 | public GH_Speed() { Value = Speed.Default; } 8 | public GH_Speed(GH_Speed goo) { Value = goo.Value; } 9 | public GH_Speed(Speed native) { Value = native; } 10 | public override IGH_Goo Duplicate() => new GH_Speed(this); 11 | public override bool IsValid => true; 12 | public override string TypeName => "Speed"; 13 | public override string TypeDescription => "Speed"; 14 | public override string ToString() => Value.ToString(); 15 | 16 | public override bool CastFrom(object source) 17 | { 18 | switch (source) 19 | { 20 | case Speed speed: 21 | Value = speed; 22 | return true; 23 | case GH_Number number: 24 | Value = new Speed(number.Value); 25 | return true; 26 | case GH_String text: 27 | { 28 | string[] texts = text.Value.Split(','); 29 | double[] values = new double[texts.Length]; 30 | 31 | for (int i = 0; i < texts.Length; i++) 32 | { 33 | if (!GH_Convert.ToDouble_Secondary(texts[i], ref values[i])) 34 | return false; 35 | } 36 | 37 | if (texts.Length == 1) 38 | { 39 | Value = new Speed(values[0]); 40 | return true; 41 | } 42 | else if (texts.Length == 2) 43 | { 44 | Value = new Speed(values[0], values[1]); 45 | return true; 46 | } 47 | 48 | break; 49 | } 50 | } 51 | return false; 52 | } 53 | 54 | public override bool CastTo<Q>(ref Q target) 55 | { 56 | if (typeof(Q).IsAssignableFrom(typeof(Speed))) 57 | { 58 | target = (Q)(object)Value; 59 | return true; 60 | } 61 | 62 | return false; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_Target.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using Grasshopper.Kernel.Types; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class GH_Target : GH_Goo<Target> 7 | { 8 | public GH_Target() { Value = Target.Default; } 9 | public GH_Target(GH_Target goo) { Value = goo.Value; } 10 | public GH_Target(Target native) { Value = native; } 11 | public override IGH_Goo Duplicate() => new GH_Target(this); 12 | public override bool IsValid => true; 13 | public override string TypeName => "Target"; 14 | public override string TypeDescription => "Target"; 15 | public override string ToString() => Value.ToString(); 16 | 17 | public override bool CastFrom(object source) 18 | { 19 | switch (source) 20 | { 21 | case Target target: 22 | Value = target; 23 | return true; 24 | case GH_Point point: 25 | Value = new CartesianTarget(new Plane(point.Value, Vector3d.XAxis, Vector3d.YAxis)); 26 | return true; 27 | case GH_Plane plane: 28 | Value = new CartesianTarget(plane.Value); 29 | return true; 30 | case GH_String text: 31 | { 32 | string[] jointsText = text.Value.Split(','); 33 | 34 | if (jointsText.Length != 6 && jointsText.Length != 7) 35 | return false; 36 | 37 | var joints = new double[jointsText.Length]; 38 | 39 | for (int i = 0; i < jointsText.Length; i++) 40 | if (!GH_Convert.ToDouble_Secondary(jointsText[i], ref joints[i])) return false; 41 | 42 | Value = new JointTarget(joints); 43 | return true; 44 | } 45 | } 46 | 47 | return false; 48 | } 49 | 50 | public override bool CastTo<Q>(ref Q target) 51 | { 52 | if (typeof(Q).IsAssignableFrom(typeof(Target))) 53 | { 54 | target = (Q)(object)Value; 55 | return true; 56 | } 57 | 58 | return false; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_Tool.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel.Types; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class GH_Tool : GH_Goo<Tool> 6 | { 7 | public GH_Tool() { Value = Tool.Default; } 8 | public GH_Tool(GH_Tool goo) { Value = goo.Value; } 9 | public GH_Tool(Tool native) { Value = native; } 10 | public override IGH_Goo Duplicate() => new GH_Tool(this); 11 | public override bool IsValid => true; 12 | public override string TypeName => "Tool"; 13 | public override string TypeDescription => "Tool"; 14 | public override string ToString() => Value.ToString(); 15 | public override bool CastFrom(object source) 16 | { 17 | switch (source) 18 | { 19 | case Tool tool: 20 | Value = tool; 21 | return true; 22 | default: 23 | return false; 24 | } 25 | } 26 | 27 | public override bool CastTo<Q>(ref Q target) 28 | { 29 | if (typeof(Q).IsAssignableFrom(typeof(Tool))) 30 | { 31 | target = (Q)(object)Value; 32 | return true; 33 | } 34 | 35 | if (typeof(Q) == typeof(GH_Plane)) 36 | { 37 | target = (Q)(object)new GH_Plane(Value.Tcp); 38 | return true; 39 | } 40 | 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_Toolpath.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel.Types; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class GH_Toolpath : GH_Goo<IToolpath> 6 | { 7 | public GH_Toolpath() { Value = new SimpleToolpath(); } 8 | public GH_Toolpath(IToolpath native) { Value = native; } 9 | public override IGH_Goo Duplicate() => new GH_Toolpath(Value); 10 | public override bool IsValid => true; 11 | public override string TypeName => "Toolpath"; 12 | public override string TypeDescription => "Toolpath"; 13 | public override string ToString() 14 | { 15 | return Value.Targets switch 16 | { 17 | IList<Target> targets => $"Toolpath with ({targets.Count} targets)", 18 | Target target => target.ToString(), 19 | _ => "Toolpath", 20 | }; 21 | } 22 | 23 | public override bool CastFrom(object source) 24 | { 25 | switch (source) 26 | { 27 | case GH_Target target: 28 | Value = target.Value; 29 | return true; 30 | case IToolpath toolpath: 31 | Value = toolpath; 32 | return true; 33 | default: 34 | return false; 35 | } 36 | } 37 | 38 | public override bool CastTo<Q>(ref Q target) 39 | { 40 | if (typeof(Q).IsAssignableFrom(typeof(IToolpath))) 41 | { 42 | target = (Q)(object)Value; 43 | return true; 44 | } 45 | 46 | return false; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Goos/GH_Zone.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel.Types; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class GH_Zone : GH_Goo<Zone> 6 | { 7 | public GH_Zone() { Value = Zone.Default; } 8 | public GH_Zone(GH_Zone goo) { Value = goo.Value; } 9 | public GH_Zone(Zone native) { Value = native; } 10 | public override IGH_Goo Duplicate() => new GH_Zone(this); 11 | public override bool IsValid => true; 12 | public override string TypeName => "Zone"; 13 | public override string TypeDescription => "Zone"; 14 | public override string ToString() => Value.ToString(); 15 | 16 | public override bool CastFrom(object source) 17 | { 18 | switch (source) 19 | { 20 | case Zone zone: 21 | Value = zone; 22 | return true; 23 | case GH_Number number: 24 | Value = new Zone(number.Value); 25 | return true; 26 | case GH_String text: 27 | { 28 | string[] texts = text.Value.Split(','); 29 | double[] values = new double[texts.Length]; 30 | 31 | for (int i = 0; i < texts.Length; i++) 32 | { 33 | if (!GH_Convert.ToDouble_Secondary(texts[i], ref values[i])) 34 | return false; 35 | } 36 | 37 | if (texts.Length == 1) 38 | { 39 | Value = new Zone(values[0]); 40 | return true; 41 | } 42 | else if (texts.Length == 2) 43 | { 44 | Value = new Zone(values[0], values[1]); 45 | return true; 46 | } 47 | 48 | break; 49 | } 50 | } 51 | 52 | double value = 0; 53 | if (GH_Convert.ToDouble_Secondary(source, ref value)) 54 | { 55 | Value = new Zone(value); 56 | return true; 57 | } 58 | else 59 | { 60 | return false; 61 | } 62 | } 63 | 64 | public override bool CastTo<Q>(ref Q target) 65 | { 66 | if (typeof(Q).IsAssignableFrom(typeof(Zone))) 67 | { 68 | target = (Q)(object)Value; 69 | return true; 70 | } 71 | 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Obsolete/CreateSpeed.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using static System.Math; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | [Obsolete("Replace with the new CreateSpeed component")] 7 | public class CreateSpeed : GH_Component 8 | { 9 | public CreateSpeed() : base("Create speed", "Speed", "Creates a target speed.", "Robots", "Components") { } 10 | public override GH_Exposure Exposure => GH_Exposure.hidden; 11 | public override Guid ComponentGuid => new("{BD11418C-74E1-4B13-BE1A-AF105906E1BC}"); 12 | protected override Bitmap Icon => Util.GetIcon("iconSpeed"); 13 | 14 | protected override void RegisterInputParams(GH_InputParamManager pManager) 15 | { 16 | pManager.AddNumberParameter("Translation", "T", "TCP translation speed", GH_ParamAccess.item, 100.0); 17 | pManager.AddNumberParameter("Rotation", "R", "TCP rotation and swivel speed", GH_ParamAccess.item, PI); 18 | pManager.AddNumberParameter("External translation", "Et", "External axes translation speed", GH_ParamAccess.item, 5000.0); 19 | pManager.AddNumberParameter("External rotation", "Er", "External axes rotation speed", GH_ParamAccess.item, PI * 6); 20 | } 21 | 22 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 23 | { 24 | pManager.AddParameter(new SpeedParameter(), "Speed", "S", "Speed instance", GH_ParamAccess.item); 25 | } 26 | 27 | protected override void SolveInstance(IGH_DataAccess DA) 28 | { 29 | double translationSpeed = 0, rotationSpeed = 0, translationExternal = 0, rotationExternal = 0; 30 | 31 | if (!DA.GetData(0, ref translationSpeed)) return; 32 | if (!DA.GetData(1, ref rotationSpeed)) return; 33 | if (!DA.GetData(2, ref translationExternal)) return; 34 | if (!DA.GetData(3, ref rotationExternal)) return; 35 | 36 | var speed = new Speed(translationSpeed, rotationSpeed, translationExternal, rotationExternal); 37 | DA.SetData(0, speed); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/CommandParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class CommandParameter : GH_PersistentParam<GH_Command> 4 | { 5 | public CommandParameter() : base("Command parameter", "Command", "This is a robot command", "Robots", "Parameters") { } 6 | public override GH_Exposure Exposure => GH_Exposure.tertiary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconCommandParam"); 8 | public override Guid ComponentGuid => new("{F5865990-90F3-4736-9AFF-4DD9ECEDA799}"); 9 | protected override GH_Command PreferredCast(object data) => 10 | data is Command cast ? new GH_Command(cast) : null!; 11 | 12 | protected override GH_GetterResult Prompt_Singular(ref GH_Command value) 13 | { 14 | value = new GH_Command(); 15 | return GH_GetterResult.success; 16 | } 17 | 18 | protected override GH_GetterResult Prompt_Plural(ref List<GH_Command> values) 19 | { 20 | values = []; 21 | return GH_GetterResult.success; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/FrameParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class FrameParameter : GH_PersistentParam<GH_Frame> 4 | { 5 | public FrameParameter() : base("Frame parameter", "Frame", "This is a robot frame", "Robots", "Parameters") { } 6 | public override GH_Exposure Exposure => GH_Exposure.tertiary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconFrameParam"); 8 | public override Guid ComponentGuid => new("{6A012ECB-D161-4F93-BB60-D03391DF1A7C}"); 9 | protected override GH_Frame PreferredCast(object data) => 10 | data is Frame cast ? new GH_Frame(cast) : null!; 11 | 12 | protected override GH_GetterResult Prompt_Singular(ref GH_Frame value) 13 | { 14 | value = new GH_Frame(); 15 | return GH_GetterResult.success; 16 | } 17 | 18 | protected override GH_GetterResult Prompt_Plural(ref List<GH_Frame> values) 19 | { 20 | values = []; 21 | return GH_GetterResult.success; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/JointsParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class JointsParameter : GH_PersistentParam<GH_Joints> 4 | { 5 | public JointsParameter() : base("Joints parameter", "Joints", "A list of numbers representing joint values", "Robots", "Parameters") { } 6 | public override GH_Exposure Exposure => GH_Exposure.tertiary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconJointsParam"); 8 | public override Guid ComponentGuid => new("{2A47BF40-61D3-46D2-AA32-AF794C2F240B}"); 9 | protected override GH_Joints PreferredCast(object data) => 10 | data is double[] cast ? new GH_Joints(cast) : null!; 11 | 12 | protected override GH_GetterResult Prompt_Singular(ref GH_Joints value) 13 | { 14 | value = new GH_Joints(); 15 | return GH_GetterResult.success; 16 | } 17 | 18 | protected override GH_GetterResult Prompt_Plural(ref List<GH_Joints> values) 19 | { 20 | values = []; 21 | return GH_GetterResult.success; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/PostProcessorParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class PostProcessorParameter : GH_Param<GH_PostProcessor> 4 | { 5 | public PostProcessorParameter() : base("PostProcessor parameter", "PostProcessor", "This is an alternative post-processor.", "Robots", "Parameters", GH_ParamAccess.item) { } 6 | public override GH_Exposure Exposure => GH_Exposure.primary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconPostProcessorParam"); 8 | public override Guid ComponentGuid => new("12e20f7a-82c9-400c-bbee-c6ba46b78046"); 9 | protected override GH_PostProcessor PreferredCast(object data) => 10 | data is IPostProcessor cast ? new GH_PostProcessor(cast) : null!; 11 | } 12 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/ProgramParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class ProgramParameter : GH_Param<GH_Program> 4 | { 5 | public ProgramParameter() : base("Program parameter", "Program", "This is a robot program", "Robots", "Parameters", GH_ParamAccess.item) { } 6 | public override GH_Exposure Exposure => GH_Exposure.quarternary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconProgramParam"); 8 | public override Guid ComponentGuid => new("{9C4F1BB6-5FA2-44DA-B7EA-421AF31DA054}"); 9 | protected override GH_Program PreferredCast(object data) => 10 | data is IProgram cast ? new GH_Program(cast) : null!; 11 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/RobotSystemParameter.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class RobotSystemParameter : GH_Param<GH_RobotSystem>, IGH_PreviewObject 6 | { 7 | public RobotSystemParameter() : base("RobotSystem parameter", "RobotSystem", "This is a robot system", "Robots", "Parameters", GH_ParamAccess.item) { } 8 | public override GH_Exposure Exposure => GH_Exposure.primary; 9 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconRobotParam"); 10 | public override Guid ComponentGuid => new("{3DBDF573-248C-44B5-8D46-184657A56BCB}"); 11 | protected override GH_RobotSystem PreferredCast(object data) => 12 | data is RobotSystem cast ? new GH_RobotSystem(cast) : null!; 13 | public bool Hidden { get; set; } 14 | public bool IsPreviewCapable => true; 15 | public BoundingBox ClippingBox => Preview_ComputeClippingBox(); 16 | public void DrawViewportWires(IGH_PreviewArgs args) => Preview_DrawMeshes(args); 17 | public void DrawViewportMeshes(IGH_PreviewArgs args) => Preview_DrawMeshes(args); 18 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/SpeedParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class SpeedParameter : GH_PersistentParam<GH_Speed> 4 | { 5 | public SpeedParameter() : base("Speed parameter", "Speed", "This is a robot speed", "Robots", "Parameters") { } 6 | public override GH_Exposure Exposure => GH_Exposure.tertiary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconSpeedParam"); 8 | public override Guid ComponentGuid => new("{0B329813-13A0-48C4-B89A-65F289A4FF28}"); 9 | protected override GH_Speed PreferredCast(object data) => 10 | data is Speed cast ? new GH_Speed(cast) : null!; 11 | 12 | protected override GH_GetterResult Prompt_Singular(ref GH_Speed value) 13 | { 14 | value = new GH_Speed(); 15 | return GH_GetterResult.success; 16 | } 17 | 18 | protected override GH_GetterResult Prompt_Plural(ref List<GH_Speed> values) 19 | { 20 | values = []; 21 | return GH_GetterResult.success; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/TargetParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class TargetParameter : GH_PersistentParam<GH_Target> 4 | { 5 | public TargetParameter() : base("Target parameter", "Target", "This is a robot target", "Robots", "Parameters") { } 6 | public override GH_Exposure Exposure => GH_Exposure.secondary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconTargetParam"); 8 | public override Guid ComponentGuid => new("{BEB590A9-905E-42ED-AB08-3E999EA94553}"); 9 | protected override GH_Target PreferredCast(object data) => 10 | data is Target cast ? new GH_Target(cast) : null!; 11 | 12 | protected override GH_GetterResult Prompt_Singular(ref GH_Target value) 13 | { 14 | value = new GH_Target(); 15 | return GH_GetterResult.success; 16 | } 17 | 18 | protected override GH_GetterResult Prompt_Plural(ref List<GH_Target> values) 19 | { 20 | values = []; 21 | return GH_GetterResult.success; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/ToolParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class ToolParameter : GH_PersistentParam<GH_Tool> 4 | { 5 | public ToolParameter() : base("Tool parameter", "Tool", "This is a robot tool", "Robots", "Parameters") { } 6 | public override GH_Exposure Exposure => GH_Exposure.tertiary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconToolParam"); 8 | public override Guid ComponentGuid => new("{073A02A6-2166-4387-9482-2EE3282E9209}"); 9 | protected override GH_Tool PreferredCast(object data) => 10 | data is Tool cast ? new GH_Tool(cast) : null!; 11 | 12 | protected override GH_GetterResult Prompt_Singular(ref GH_Tool value) 13 | { 14 | value = new GH_Tool(); 15 | return GH_GetterResult.success; 16 | } 17 | 18 | protected override GH_GetterResult Prompt_Plural(ref List<GH_Tool> values) 19 | { 20 | values = []; 21 | return GH_GetterResult.success; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/ToolpathParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class ToolpathParameter : GH_PersistentParam<GH_Toolpath> 4 | { 5 | public ToolpathParameter() : base("Toolpath parameter", "Toolpath", "This is a robot toolpath", "Robots", "Parameters") { } 6 | public override GH_Exposure Exposure => GH_Exposure.secondary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconToolpathParam"); 8 | public override Guid ComponentGuid => new("{715AEDCE-14E8-400B-A226-9806FC3CB7B3}"); 9 | protected override GH_Toolpath PreferredCast(object data) => 10 | data is IToolpath cast ? new GH_Toolpath(cast) : null!; 11 | 12 | protected override GH_GetterResult Prompt_Singular(ref GH_Toolpath value) 13 | { 14 | value = new GH_Toolpath(); 15 | return GH_GetterResult.success; 16 | } 17 | 18 | protected override GH_GetterResult Prompt_Plural(ref List<GH_Toolpath> values) 19 | { 20 | values = []; 21 | return GH_GetterResult.success; 22 | } 23 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Parameters/ZoneParameter.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class ZoneParameter : GH_PersistentParam<GH_Zone> 4 | { 5 | public ZoneParameter() : base("Zone parameter", "Zone", "This is a robot approximation zone", "Robots", "Parameters") { } 6 | public override GH_Exposure Exposure => GH_Exposure.tertiary; 7 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconZoneParam"); 8 | public override Guid ComponentGuid => new("{458855D3-F671-4A50-BDA1-6AD3B7A5EC70}"); 9 | protected override GH_Zone PreferredCast(object data) => 10 | data is Zone cast ? new GH_Zone(cast) : null!; 11 | 12 | protected override GH_GetterResult Prompt_Singular(ref GH_Zone value) 13 | { 14 | value = new GH_Zone(); 15 | return GH_GetterResult.success; 16 | } 17 | 18 | protected override GH_GetterResult Prompt_Plural(ref List<GH_Zone> values) 19 | { 20 | values = []; 21 | return GH_GetterResult.success; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Program/CustomCode.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel.Types; 2 | using Grasshopper.Kernel.Data; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class CustomCode : GH_Component 7 | { 8 | public CustomCode() : base("Custom code", "Custom", "Creates a program using manufacturer specific custom code. This program cannot be simulated", "Robots", "Components") { } 9 | public override GH_Exposure Exposure => GH_Exposure.quarternary; 10 | public override Guid ComponentGuid => new("{FF997511-4A84-4426-AB62-AF94D19FF58F}"); 11 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconCustomCode"); 12 | 13 | protected override void RegisterInputParams(GH_InputParamManager pManager) 14 | { 15 | pManager.AddParameter(new ProgramParameter(), "Program", "P", "Program", GH_ParamAccess.item); 16 | pManager.AddTextParameter("Code", "C", "Custom code", GH_ParamAccess.tree); 17 | } 18 | 19 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 20 | { 21 | pManager.AddParameter(new ProgramParameter(), "Program", "P", "Program", GH_ParamAccess.item); 22 | } 23 | 24 | protected override void SolveInstance(IGH_DataAccess DA) 25 | { 26 | IProgram? program = null; 27 | 28 | if (!DA.GetData(0, ref program) || program is null) return; 29 | if (!DA.GetDataTree(1, out GH_Structure<GH_String> codeTree)) return; 30 | 31 | if (program is not Program p) 32 | { 33 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, " Input program cannot have custom code"); 34 | DA.AbortComponentSolution(); 35 | return; 36 | } 37 | 38 | var code = new List<List<List<string>>> 39 | { 40 | new() 41 | }; 42 | 43 | foreach (var branch in codeTree.Branches) 44 | { 45 | code[0].Add(branch.Select(s => s.Value).ToList()); 46 | } 47 | 48 | var programCode = program.Code; 49 | if (programCode is not null && programCode.Count > 0) 50 | { 51 | var newProgram = p.CustomCode(code); 52 | DA.SetData(0, newProgram); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Program/SaveProgram.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class SaveProgram : GH_Component 4 | { 5 | public SaveProgram() : base("Save program", "SaveProg", "Saves a program to a text file.", "Robots", "Components") { } 6 | public override GH_Exposure Exposure => GH_Exposure.senary; 7 | public override Guid ComponentGuid => new("{1DE69EAA-AA4C-44F2-8748-F19B041F8F58}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconSave"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddParameter(new ProgramParameter(), "Program", "P", "Program", GH_ParamAccess.item); 13 | pManager.AddTextParameter("Folder", "F", "Folder", GH_ParamAccess.item); 14 | pManager[1].Optional = true; 15 | } 16 | 17 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 18 | { 19 | } 20 | 21 | protected override void SolveInstance(IGH_DataAccess DA) 22 | { 23 | IProgram? program = null; 24 | string? folder = null; 25 | 26 | if (!DA.GetData(0, ref program) || program is null) return; 27 | if (!DA.GetData(1, ref folder) || folder is null) return; 28 | 29 | try 30 | { 31 | program.Save(folder); 32 | } 33 | catch (Exception e) 34 | { 35 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $" Program could not be saved: {e.Message}"); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Program/SimulationForm.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using Eto.Drawing; 3 | using Eto.Forms; 4 | 5 | namespace Robots.Grasshopper; 6 | 7 | class SimulationForm : ComponentForm 8 | { 9 | readonly Simulation _component; 10 | 11 | internal readonly CheckBox Play; 12 | 13 | public SimulationForm(Simulation component) 14 | { 15 | _component = component; 16 | 17 | Title = "Playback"; 18 | MinimumSize = new Size(0, 200); 19 | 20 | Padding = new Padding(5); 21 | 22 | var font = new Font(FontFamilies.Sans, 14, FontStyle.None, FontDecoration.None); 23 | var size = new Size(35, 35); 24 | 25 | Play = new CheckBox 26 | { 27 | Text = "\u25B6", 28 | Size = size, 29 | Font = font, 30 | Checked = false, 31 | TabIndex = 0 32 | }; 33 | 34 | Play.CheckedChanged += (s, e) => component.TogglePlay(); 35 | 36 | var stop = new Button 37 | { 38 | Text = "\u25FC", 39 | Size = size, 40 | Font = font, 41 | TabIndex = 1 42 | }; 43 | 44 | stop.Click += (s, e) => component.Stop(); 45 | 46 | var slider = new Slider 47 | { 48 | Orientation = Orientation.Vertical, 49 | Size = new Size(-1, -1), 50 | TabIndex = 2, 51 | MaxValue = 400, 52 | MinValue = -200, 53 | TickFrequency = 100, 54 | SnapToTick = true, 55 | Value = 100, 56 | }; 57 | 58 | slider.ValueChanged += (s, e) => component.Speed = (double)slider.Value / 100.0; ; 59 | 60 | var speedLabel = new Label 61 | { 62 | Text = "100%", 63 | VerticalAlignment = VerticalAlignment.Center, 64 | }; 65 | 66 | var layout = new DynamicLayout(); 67 | layout.BeginVertical(); 68 | layout.AddSeparateRow(padding: new Padding(10), spacing: new Size(10, 0), controls: [Play, stop]); 69 | layout.BeginGroup("Speed"); 70 | layout.AddSeparateRow(slider, speedLabel); 71 | layout.EndGroup(); 72 | layout.EndVertical(); 73 | 74 | Content = layout; 75 | } 76 | 77 | protected override void OnClosing(CancelEventArgs e) 78 | { 79 | _component.Stop(); 80 | base.OnClosing(e); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/RobotSystem/DegreesToRadians.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Grasshopper; 2 | 3 | public class DegreesToRadians : GH_Component 4 | { 5 | public DegreesToRadians() : base("Degrees to radians", "DegToRad", "Manufacturer dependent degrees to radians conversion.", "Robots", "Utility") { } 6 | public override GH_Exposure Exposure => GH_Exposure.primary; 7 | public override Guid ComponentGuid => new("{C10B3A17-5C19-4805-ACCF-839B85C4D21C}"); 8 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconAngles"); 9 | 10 | protected override void RegisterInputParams(GH_InputParamManager pManager) 11 | { 12 | pManager.AddNumberParameter("Degrees", "D", "Degrees", GH_ParamAccess.list); 13 | pManager.AddParameter(new RobotSystemParameter(), "Robot system", "R", "Robot system", GH_ParamAccess.item); 14 | pManager.AddIntegerParameter("Mechanical group", "G", "Mechanical group index", GH_ParamAccess.item, 0); 15 | } 16 | 17 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 18 | { 19 | pManager.AddParameter(new JointsParameter(), "Radians", "R", "Radians", GH_ParamAccess.item); 20 | } 21 | 22 | protected override void SolveInstance(IGH_DataAccess DA) 23 | { 24 | var degrees = new List<double>(6); 25 | RobotSystem? robotSystem = null; 26 | int group = 0; 27 | 28 | if (!DA.GetDataList(0, degrees)) return; 29 | if (!DA.GetData(1, ref robotSystem) || robotSystem is null) return; 30 | if (!DA.GetData(2, ref group)) return; 31 | 32 | var radians = degrees.Select((x, i) => robotSystem.DegreeToRadian(x, i, group)).ToArray(); 33 | DA.SetData(0, radians); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/RobotSystem/FromPlane.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class FromPlane : GH_Component 6 | { 7 | public FromPlane() : base("From plane", "FromPlane", "Returns a list of numbers from a plane. The first 3 numbers are the x, y, and z coordinates of the origin. The last 3 or 4 values correspond to Euler angles in degrees or quaternion values respectively.", "Robots", "Utility") { } 8 | public override GH_Exposure Exposure => GH_Exposure.primary; 9 | public override Guid ComponentGuid => new("{03353E74-E816-4E0A-AF9A-8AFB4C111D0B}"); 10 | protected override System.Drawing.Bitmap Icon => Util.GetIcon("iconToPlane"); 11 | 12 | protected override void RegisterInputParams(GH_InputParamManager pManager) 13 | { 14 | pManager.AddPlaneParameter("Plane", "P", "Plane to convert to Euler, quaternion or axis angle values.", GH_ParamAccess.item); 15 | pManager.AddParameter(new RobotSystemParameter(), "Robot system", "R", "The robot system will select the orientation type (ABB = quaternions, KUKA = Euler angles in degrees, UR = axis angles in radians). If this input is left unconnected, the 3D rotation will be expressed in quaternions.", GH_ParamAccess.item); 16 | pManager[1].Optional = true; 17 | } 18 | 19 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 20 | { 21 | pManager.AddNumberParameter("Numbers", "N", "The first 3 numbers are the x, y and z coordinates of the origin. The last 3 or 4 numbers represent a 3D rotation.", GH_ParamAccess.list); 22 | } 23 | 24 | protected override void SolveInstance(IGH_DataAccess DA) 25 | { 26 | Plane plane = default; 27 | RobotSystem? robotSystem = null; 28 | 29 | if (!DA.GetData(0, ref plane)) return; 30 | DA.GetData(1, ref robotSystem); 31 | 32 | double[] numbers; 33 | 34 | if (robotSystem is null) 35 | { 36 | AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, " No robot system supplied, defaulting to quaternion conversion"); 37 | numbers = SystemAbb.PlaneToQuaternion(plane); 38 | } 39 | else 40 | { 41 | numbers = robotSystem.PlaneToNumbers(plane); 42 | } 43 | 44 | DA.SetDataList(0, numbers); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/RobotSystem/LoadFrame.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using System.Drawing; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class LoadFrame : GH_Component 7 | { 8 | public LoadFrame() : base("Load frame", "LoadFrame", "Loads a frame from the library.", "Robots", "Components") { } 9 | public override GH_Exposure Exposure => GH_Exposure.primary; 10 | public override Guid ComponentGuid => new("{71C2364B-BC32-48E7-9049-406EF7059381}"); 11 | protected override Bitmap Icon => Util.GetIcon("iconFrame"); 12 | 13 | protected override void RegisterInputParams(GH_InputParamManager pManager) 14 | { 15 | pManager.AddTextParameter("Name", "N", "Name of the frame", GH_ParamAccess.item); 16 | } 17 | 18 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 19 | { 20 | pManager.AddParameter(new FrameParameter(), "Frame", "F", "Frame", GH_ParamAccess.item); 21 | } 22 | 23 | public override void AddedToDocument(GH_Document document) 24 | { 25 | base.AddedToDocument(document); 26 | LibraryParam.CreateIfEmpty(document, this, ElementType.Frame); 27 | } 28 | 29 | protected override void SolveInstance(IGH_DataAccess DA) 30 | { 31 | string? name = null; 32 | 33 | if (!DA.GetData(0, ref name)) return; 34 | 35 | if (name is null) 36 | { 37 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $" Input parameter N cannot be null"); 38 | DA.AbortComponentSolution(); 39 | return; 40 | } 41 | 42 | try 43 | { 44 | var frame = FileIO.LoadFrame(name); 45 | DA.SetData(0, frame); 46 | } 47 | catch (Exception e) 48 | { 49 | var message = e is XmlException ex 50 | ? $" Invalid XML syntax in \"{Path.GetFileName(ex.SourceUri)}\"" 51 | : e.Message; 52 | 53 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, message); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/RobotSystem/LoadTool.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using System.Drawing; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class LoadTool : GH_Component 7 | { 8 | public LoadTool() : base("Load tool", "LoadTool", "Loads a tool from the library.", "Robots", "Components") { } 9 | public override GH_Exposure Exposure => GH_Exposure.primary; 10 | public override Guid ComponentGuid => new("{542aa5fd-4f02-4ee5-a2a0-02b0fac8777f}"); 11 | protected override Bitmap Icon => Util.GetIcon("iconTool"); 12 | 13 | protected override void RegisterInputParams(GH_InputParamManager pManager) 14 | { 15 | pManager.AddTextParameter("Name", "N", "Name of the tool", GH_ParamAccess.item); 16 | } 17 | 18 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 19 | { 20 | pManager.AddParameter(new ToolParameter(), "Tool", "T", "Tool", GH_ParamAccess.item); 21 | } 22 | 23 | public override void AddedToDocument(GH_Document document) 24 | { 25 | base.AddedToDocument(document); 26 | LibraryParam.CreateIfEmpty(document, this, ElementType.Tool); 27 | } 28 | 29 | protected override void SolveInstance(IGH_DataAccess DA) 30 | { 31 | string? name = null; 32 | 33 | if (!DA.GetData(0, ref name)) return; 34 | 35 | if (name is null) 36 | { 37 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, $" Input parameter N cannot be null"); 38 | DA.AbortComponentSolution(); 39 | return; 40 | } 41 | 42 | try 43 | { 44 | var tool = FileIO.LoadTool(name); 45 | DA.SetData(0, tool); 46 | } 47 | catch (Exception e) 48 | { 49 | var message = e is XmlException ex 50 | ? $" Invalid XML syntax in \"{Path.GetFileName(ex.SourceUri)}\"" 51 | : e.Message; 52 | 53 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, message); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Robots.Grasshopper.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>net48</TargetFramework> 5 | <AssemblyTitle>$(Product) Grasshopper</AssemblyTitle> 6 | 7 | <PackageId>Robots.Rhino</PackageId> 8 | <PackageIcon>iconRhino128.png</PackageIcon> 9 | <Description>$(Description) This package is for development of Rhino and Grasshopper plug-ins.</Description> 10 | <PackageTags>$(PackageTags);Rhino;Grasshopper</PackageTags> 11 | <Rhino>8</Rhino> 12 | </PropertyGroup> 13 | 14 | <ItemGroup> 15 | <Reference Include="Microsoft.CSharp" /> 16 | <Reference Include="System.Windows.Forms" /> 17 | <PackageReference Include="Grasshopper" Version="7.0.20314.3001" ExcludeAssets="runtime" /> 18 | <ProjectReference Include="..\Robots\Robots.csproj" PrivateAssets="All" /> 19 | </ItemGroup> 20 | 21 | <ItemGroup> 22 | <EmbeddedResource Include="Assets\Embed\**\*" /> 23 | <None Include="$(RootDir)build\Assets\iconRhino128.png" Pack="true" PackagePath="" Visible="false" /> 24 | <None Include="$(RootDir)build\Assets\iconRobot.png" CopyToOutputDirectory="PreserveNewest" Visible="false" /> 25 | <None Include="Build\Robots.Rhino.targets" Pack="true" PackagePath="buildTransitive" /> 26 | <None Include="$(TargetDir)$(Product).dll" Pack="true" PackagePath="lib\net48" Visible="false" /> 27 | </ItemGroup> 28 | 29 | <PropertyGroup Condition="$([MSBuild]::IsOSPlatform(Windows)) and $(Configuration) == 'Debug'"> 30 | <StartProgram>C:\Program Files\Rhino $(Rhino)\System\Rhino.exe</StartProgram> 31 | <StartArguments>/nosplash /runscript="-grasshopper window show _enter"</StartArguments> 32 | <StartAction>Program</StartAction> 33 | 34 | <PackageDir>$(AppData)\McNeel\Rhinoceros\packages\$(Rhino).0\$(Product)</PackageDir> 35 | <OutputPath>$(PackageDir)\$(Version)</OutputPath> 36 | </PropertyGroup> 37 | 38 | <Target Name="Manifest" BeforeTargets="Build" Condition="$(Configuration) == 'Debug'"> 39 | <WriteLinesToFile File="$(PackageDir)\manifest.txt" Overwrite="true" Lines="$(Version)" /> 40 | </Target> 41 | 42 | <Target Name="Rename" AfterTargets="AfterBuild" Condition="'$(ContinuePackingAfterGeneratingNuspec)' != 'true'"> 43 | <Move SourceFiles="$(TargetPath)" DestinationFiles="$(TargetDir)$(Product).gha" /> 44 | </Target> 45 | 46 | </Project> 47 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Target/ConfigParam.cs: -------------------------------------------------------------------------------- 1 | using Grasshopper.Kernel.Data; 2 | using Grasshopper.Kernel.Special; 3 | using Grasshopper.Kernel.Types; 4 | 5 | namespace Robots.Grasshopper; 6 | 7 | public class ConfigParam : GH_ValueList 8 | { 9 | public override string Name => "Flag fields"; 10 | public override string Description => "Modified value list parameter for flag fields"; 11 | public override Guid ComponentGuid => new("{0381B555-BF9C-4D68-8E5C-10B2FCB16F30}"); 12 | public override GH_Exposure Exposure => GH_Exposure.hidden; 13 | 14 | protected override void OnVolatileDataCollected() 15 | { 16 | int config = 0; 17 | 18 | if (VolatileDataCount > 0) 19 | { 20 | var values = VolatileData.get_Branch(0); 21 | 22 | foreach (var value in values) 23 | { 24 | if (value is GH_Integer integer) 25 | { 26 | config += integer.Value; 27 | } 28 | } 29 | } 30 | 31 | VolatileData.Clear(); 32 | AddVolatileData(new GH_Path(0), 0, new GH_Integer(config)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Target/CreateFrame.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using Rhino.Geometry; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class CreateFrame : GH_Component 7 | { 8 | public CreateFrame() : base("Create frame", "Frame", "Creates a frame or work plane.", "Robots", "Components") { } 9 | public override GH_Exposure Exposure => GH_Exposure.tertiary; 10 | public override Guid ComponentGuid => new("{467237C8-08F5-4104-A553-8814AACAFE51}"); 11 | protected override Bitmap Icon => Util.GetIcon("iconCreateFrame"); 12 | 13 | protected override void RegisterInputParams(GH_InputParamManager pManager) 14 | { 15 | pManager.AddPlaneParameter("Plane", "P", "Frame plane", GH_ParamAccess.item, Plane.WorldXY); 16 | pManager.AddIntegerParameter("Coupled mechanical group", "G", "Index of the mechanical group where the coupled mechanism or robot belongs, or -1 for no coupling.", GH_ParamAccess.item, -1); 17 | pManager.AddIntegerParameter("Coupled mechanism", "M", "Index of coupled mechanism or -1 for coupling of a robot in a multi robot system. If input G is -1 this has no effect.", GH_ParamAccess.item, -1); 18 | pManager.AddTextParameter("Name", "N", "Optional name for the frame.", GH_ParamAccess.item); 19 | pManager[3].Optional = true; 20 | } 21 | 22 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 23 | { 24 | pManager.AddParameter(new FrameParameter(), "Frame", "F", "Frame", GH_ParamAccess.item); 25 | } 26 | 27 | protected override void SolveInstance(IGH_DataAccess DA) 28 | { 29 | Plane plane = default; 30 | int coupledGroup = -1; 31 | int coupledMechanism = -1; 32 | string? name = null; 33 | 34 | if (!DA.GetData(0, ref plane)) return; 35 | if (!DA.GetData(1, ref coupledGroup)) return; 36 | if (!DA.GetData(2, ref coupledMechanism)) return; 37 | DA.GetData(3, ref name); 38 | 39 | try 40 | { 41 | var frame = new Frame(plane, coupledMechanism, coupledGroup, name); 42 | DA.SetData(0, frame); 43 | } 44 | catch (ArgumentException e) 45 | { 46 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.Message); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Target/CreateSpeedAccel.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using static System.Math; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class CreateSpeedAccel : GH_Component 7 | { 8 | public CreateSpeedAccel() : base("Create speed", "Speed", "Creates a target speed.", "Robots", "Components") { } 9 | public override GH_Exposure Exposure => GH_Exposure.tertiary; 10 | public override Guid ComponentGuid => new("2849cac0-4006-4531-a2a3-a37cd7e31031"); 11 | protected override Bitmap Icon => Util.GetIcon("iconSpeed"); 12 | 13 | protected override void RegisterInputParams(GH_InputParamManager pManager) 14 | { 15 | pManager.AddNumberParameter("Translation", "T", "TCP translation speed (mm/s)", GH_ParamAccess.item, 100.0); 16 | pManager.AddNumberParameter("Rotation", "R", "TCP rotation and swivel speed (rad/s)", GH_ParamAccess.item, PI); 17 | pManager.AddNumberParameter("External translation", "Et", "External axes translation speed (mm/s)", GH_ParamAccess.item, 5000.0); 18 | pManager.AddNumberParameter("External rotation", "Er", "External axes rotation speed (rad/s)", GH_ParamAccess.item, PI * 6); 19 | pManager.AddNumberParameter("Accel translation", "At", "Used only in Doosan and UR (mm/s²)", GH_ParamAccess.item, 2500); 20 | pManager.AddNumberParameter("Accel axis", "Aa", "Used in UR, Doosan and Franka Emika (rads/s²). For Franka, assumes max accel and jerk is 4PI.", GH_ParamAccess.item, 4 * PI); 21 | } 22 | 23 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 24 | { 25 | pManager.AddParameter(new SpeedParameter(), "Speed", "S", "Speed instance", GH_ParamAccess.item); 26 | } 27 | 28 | protected override void SolveInstance(IGH_DataAccess DA) 29 | { 30 | double translationSpeed = 0, rotationSpeed = 0, 31 | translationExternal = 0, rotationExternal = 0, 32 | translationAccel = 0, axisAccel = 0; 33 | 34 | if (!DA.GetData(0, ref translationSpeed)) return; 35 | if (!DA.GetData(1, ref rotationSpeed)) return; 36 | if (!DA.GetData(2, ref translationExternal)) return; 37 | if (!DA.GetData(3, ref rotationExternal)) return; 38 | if (!DA.GetData(4, ref translationAccel)) return; 39 | if (!DA.GetData(5, ref axisAccel)) return; 40 | 41 | Speed speed = new(translationSpeed, rotationSpeed, translationExternal, rotationExternal) 42 | { 43 | TranslationAccel = translationAccel, 44 | AxisAccel = axisAccel 45 | }; 46 | 47 | DA.SetData(0, speed); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Target/DeconstructToolpath.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | public class DeconstructToolpath : GH_Component 6 | { 7 | public DeconstructToolpath() : base("Deconstruct Toolpath", "DeconstructToolpath", "Deconstructs a Toolpath parameter.", "Robots", "Components") { } 8 | public override GH_Exposure Exposure => GH_Exposure.secondary; 9 | public override Guid ComponentGuid => new("78ac97c6-aa8e-4048-88e7-5eeff1f8686c"); 10 | protected override Bitmap Icon => Util.GetIcon("iconDeconstructToolpath"); 11 | 12 | protected override void RegisterInputParams(GH_InputParamManager pManager) 13 | { 14 | pManager.AddParameter(new ToolpathParameter(), "Toolpath", "T", "Toolpath", GH_ParamAccess.item); 15 | } 16 | 17 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 18 | { 19 | pManager.AddParameter(new TargetParameter(), "Targets", "T", "Targets", GH_ParamAccess.list); 20 | } 21 | 22 | protected override void SolveInstance(IGH_DataAccess DA) 23 | { 24 | GH_Toolpath? toolpath = null; 25 | 26 | if (!DA.GetData(0, ref toolpath) || toolpath is null) return; 27 | 28 | try 29 | { 30 | var targets = toolpath.Value.Targets; 31 | DA.SetDataList(0, targets); 32 | } 33 | catch (ArgumentException e) 34 | { 35 | AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.Message); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Util.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace Robots.Grasshopper; 4 | 5 | static class Util 6 | { 7 | public static Bitmap GetIcon(string name) 8 | { 9 | var icon = $"Robots.Grasshopper.Assets.Embed.{name}.png"; 10 | var assembly = typeof(RobotsInfo).Assembly; 11 | using var stream = assembly.GetManifestResourceStream(icon); 12 | return new Bitmap(stream); 13 | } 14 | } -------------------------------------------------------------------------------- /src/Robots.Grasshopper/Visualization/DrawSimpleTrail.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using Grasshopper.Kernel.Types; 3 | 4 | namespace Robots.Grasshopper; 5 | 6 | public class DrawSimpleTrail : GH_Component 7 | { 8 | SimpleTrail? _trail; 9 | Program? _program; 10 | 11 | public DrawSimpleTrail() : base("Simple trail", "Trail", "Draws a trail behind the TCP. To be used with the simulation component.", "Robots", "Utility") { } 12 | public override GH_Exposure Exposure => GH_Exposure.secondary; 13 | public override Guid ComponentGuid => new("{20F09C83-25A5-453B-B0C9-673CD784A52F}"); 14 | protected override Bitmap Icon => Util.GetIcon("iconSimpleTrail"); 15 | 16 | protected override void RegisterInputParams(GH_InputParamManager pManager) 17 | { 18 | pManager.AddParameter(new ProgramParameter(), "Program", "P", "Connect to the program output from the simulation component", GH_ParamAccess.item); 19 | pManager.AddNumberParameter("Length", "L", "Length of trail", GH_ParamAccess.item, 500); 20 | pManager.AddIntegerParameter("Mechanical group", "M", "Index of mechanical group", GH_ParamAccess.item, 0); 21 | } 22 | 23 | protected override void RegisterOutputParams(GH_OutputParamManager pManager) 24 | { 25 | pManager.AddCurveParameter("Trail", "C", "Trail polyline", GH_ParamAccess.list); 26 | } 27 | 28 | protected override void SolveInstance(IGH_DataAccess DA) 29 | { 30 | IProgram? program = null; 31 | double length = 0; 32 | int mechanicalGroup = 0; 33 | 34 | if (!DA.GetData(0, ref program) || program is null) return; 35 | if (!DA.GetData(1, ref length)) return; 36 | if (!DA.GetData(2, ref mechanicalGroup)) return; 37 | 38 | if (!program.HasSimulation) 39 | { 40 | AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, " Input program cannot be animated"); 41 | DA.AbortComponentSolution(); 42 | return; 43 | } 44 | 45 | if (program != _program) 46 | { 47 | _program = (Program)program; 48 | _trail = new SimpleTrail(_program, length, mechanicalGroup); 49 | } 50 | 51 | if (_trail is not null) 52 | { 53 | _trail.Length = length; 54 | _trail.Update(); 55 | 56 | if (_trail.Polyline.Count >= 2) 57 | DA.SetData(0, new GH_Curve(_trail.Polyline.ToNurbsCurve())); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Robots.Grasshopper/build/Robots.Rhino.targets: -------------------------------------------------------------------------------- 1 | <Project> 2 | 3 | <Target Name="RemoveRobotsReferences" AfterTargets="AfterResolveReferences"> 4 | <ItemGroup> 5 | <ReferenceCopyLocalPaths 6 | Remove="@(ReferenceCopyLocalPaths)" 7 | Condition=" 8 | %(ReferenceCopyLocalPaths.FileName) == 'Robots' 9 | or %(ReferenceCopyLocalPaths.FileName) == 'Robots.Grasshopper'" 10 | /> 11 | </ItemGroup> 12 | </Target> 13 | 14 | </Project> 15 | -------------------------------------------------------------------------------- /src/Robots/Commands/Command.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Robots; 3 | 4 | public abstract class Command(string? name = null) : TargetAttribute(name) 5 | { 6 | public static Command Default { get; } = new Commands.Custom("DefaultCommand"); 7 | 8 | protected Dictionary<Manufacturers, Func<RobotSystem, string>> _declarations = new(8); 9 | protected Dictionary<Manufacturers, Func<RobotSystem, Target, string>> _commands = new(8); 10 | 11 | protected virtual void ErrorChecking(RobotSystem robotSystem) { } 12 | 13 | protected virtual void Populate() { } 14 | public bool RunBefore { get; set; } 15 | 16 | internal virtual IEnumerable<Command> Flatten() 17 | { 18 | if (this != Default) 19 | yield return this; 20 | } 21 | 22 | void Init(RobotSystem robot) 23 | { 24 | if (_commands.Count > 0 || _declarations.Count > 0) 25 | return; 26 | 27 | ErrorChecking(robot); 28 | Populate(); 29 | } 30 | 31 | internal string Declaration(Program program) 32 | { 33 | var robot = program.RobotSystem; 34 | Init(robot); 35 | 36 | if (_declarations.TryGetValue(robot.Manufacturer, out var declaration)) 37 | return declaration(robot); 38 | 39 | if (_declarations.TryGetValue(Manufacturers.All, out declaration)) 40 | return declaration(robot); 41 | 42 | return ""; 43 | } 44 | 45 | internal string Code(Program program, Target target) 46 | { 47 | var robot = program.RobotSystem; 48 | Init(robot); 49 | 50 | if (_commands.TryGetValue(robot.Manufacturer, out var command)) 51 | return command(robot, target); 52 | 53 | if (_commands.TryGetValue(Manufacturers.All, out command)) 54 | return command(robot, target); 55 | 56 | program.Warnings.Add($"Command {Name} not implemented for {robot.Manufacturer} robots."); 57 | 58 | return ""; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Robots/Commands/Custom.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Robots.Commands; 3 | 4 | public class Custom : Command 5 | { 6 | readonly Dictionary<Manufacturers, string> _customCommands = []; 7 | readonly Dictionary<Manufacturers, string> _customDeclarations = []; 8 | 9 | public Custom(string name = "CustomCommand", Manufacturers manufacturer = Manufacturers.All, string? command = null, string? declaration = null) : base(name) 10 | { 11 | AddCommand(manufacturer, command, declaration); 12 | } 13 | 14 | public void AddCommand(Manufacturers manufacturer, string? command, string? declaration) 15 | { 16 | if (command is not null) 17 | _customCommands.Add(manufacturer, command); 18 | 19 | if (declaration is not null) 20 | _customDeclarations.Add(manufacturer, declaration); 21 | } 22 | 23 | protected override void Populate() 24 | { 25 | foreach (var command in _customCommands) 26 | _commands.Add(command.Key, (_, __) => command.Value); 27 | 28 | foreach (var declaration in _customDeclarations) 29 | _declarations.Add(declaration.Key, _ => declaration.Value); 30 | } 31 | 32 | public override string ToString() => $"Command ({Name})"; 33 | } 34 | -------------------------------------------------------------------------------- /src/Robots/Commands/Group.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace Robots.Commands; 4 | 5 | public class Group : Command, IList<Command> 6 | { 7 | readonly List<Command> _commandList = []; 8 | 9 | public Group() { } 10 | 11 | public Group(IEnumerable<Command> commands) : base("GroupCommand") 12 | { 13 | _commandList.AddRange(commands); 14 | } 15 | 16 | // IList implementation 17 | public Command this[int index] 18 | { 19 | get => _commandList[index]; 20 | set => _commandList[index] = value; 21 | } 22 | 23 | public int IndexOf(Command item) => _commandList.IndexOf(item); 24 | public void Insert(int index, Command item) => _commandList.Insert(index, item); 25 | public void RemoveAt(int index) => _commandList.RemoveAt(index); 26 | public int Count => _commandList.Count; 27 | public bool IsReadOnly => false; 28 | public void Add(Command item) => _commandList.Add(item); 29 | public void Clear() => _commandList.Clear(); 30 | public bool Contains(Command item) => _commandList.Contains(item); 31 | public void CopyTo(Command[] array, int arrayIndex) => _commandList.CopyTo(array, arrayIndex); 32 | public bool Remove(Command item) => _commandList.Remove(item); 33 | public IEnumerator<Command> GetEnumerator() => _commandList.GetEnumerator(); 34 | IEnumerator IEnumerable.GetEnumerator() => _commandList.GetEnumerator(); 35 | 36 | public void AddRange(IEnumerable<Command> source) => _commandList.AddRange(source); 37 | 38 | internal override IEnumerable<Command> Flatten() 39 | { 40 | return _commandList.SelectMany(c => c.Flatten()); 41 | } 42 | public override string ToString() => $"Command (Group with {Count} commands)"; 43 | } 44 | -------------------------------------------------------------------------------- /src/Robots/Commands/Message.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Commands; 2 | 3 | public class Message(string message) : Command 4 | { 5 | readonly string _message = message; 6 | 7 | protected override void Populate() 8 | { 9 | _commands.Add(Manufacturers.ABB, (_, _) => $"TPWrite \"{_message}\";"); 10 | _commands.Add(Manufacturers.KUKA, (_, _) => $"; \"{_message}\""); 11 | _commands.Add(Manufacturers.UR, (_, _) => $"textmsg(\"{_message}\")"); 12 | _commands.Add(Manufacturers.Staubli, (_, _) => $"putln(\"{_message}\")"); 13 | _commands.Add(Manufacturers.FrankaEmika, (_, _) => $"print(\"{_message}\")"); 14 | _commands.Add(Manufacturers.Doosan, (_, _) => $"tp_log(\"{_message}\")"); 15 | _commands.Add(Manufacturers.Fanuc, (_, _) => $":MESSAGE[\"{_message}\"] ;"); 16 | _commands.Add(Manufacturers.Igus, (_, _) => $"<Comment Descr=\"{_message}\" />"); 17 | _commands.Add(Manufacturers.Jaka, (_, _) => $"print(\"{_message}\")"); 18 | } 19 | 20 | public override string ToString() => $"Command (Message \"{_message}\")"; 21 | } 22 | -------------------------------------------------------------------------------- /src/Robots/Commands/Stop.cs: -------------------------------------------------------------------------------- 1 | namespace Robots.Commands; 2 | 3 | public class Stop : Command 4 | { 5 | public Stop() { } 6 | 7 | protected override void Populate() 8 | { 9 | _commands.Add(Manufacturers.ABB, (_, _) => "Stop;"); 10 | _commands.Add(Manufacturers.KUKA, (_, _) => "HALT"); 11 | _commands.Add(Manufacturers.UR, (_, _) => "pause program"); 12 | _commands.Add(Manufacturers.Doosan, (_, _) => "wait_nudge()"); 13 | //_commands.Add(Manufacturers.Staubli, (_, __) => "wait(true)"); 14 | _commands.Add(Manufacturers.Fanuc, (_, _) => ":ABORT ;"); 15 | _commands.Add(Manufacturers.Igus, (_, _) => "<Stop Descr=\"\" />"); 16 | _commands.Add(Manufacturers.Jaka, (_, _) => "pause()"); 17 | } 18 | 19 | public override string ToString() => "Command (Stop)"; 20 | } 21 | -------------------------------------------------------------------------------- /src/Robots/Geometry/Vector6d.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Robots; 3 | 4 | public struct Vector6d 5 | { 6 | // static 7 | 8 | public static Vector6d Map<T>(T[] array, Func<T, double> projection) 9 | { 10 | if (array.Length != 6) 11 | throw new ArgumentOutOfRangeException(nameof(array), " Array length should be 6"); 12 | 13 | Vector6d result = default; 14 | 15 | for (int i = 0; i < 6; i++) 16 | result[i] = projection(array[i]); 17 | 18 | return result; 19 | } 20 | 21 | // instance 22 | 23 | public double A1; 24 | public double A2; 25 | public double A3; 26 | public double A4; 27 | public double A5; 28 | public double A6; 29 | 30 | public Vector6d(double a1, double a2, double a3, double a4, double a5, double a6) 31 | { 32 | A1 = a1; 33 | A2 = a2; 34 | A3 = a3; 35 | A4 = a4; 36 | A5 = a5; 37 | A6 = a6; 38 | } 39 | 40 | public Vector6d(double[] joints) 41 | { 42 | if (joints.Length != 6) 43 | throw new ArgumentOutOfRangeException(nameof(joints), " Array length should be 6"); 44 | 45 | A1 = joints[0]; 46 | A2 = joints[1]; 47 | A3 = joints[2]; 48 | A4 = joints[3]; 49 | A5 = joints[4]; 50 | A6 = joints[5]; 51 | } 52 | 53 | public double this[int i] 54 | { 55 | readonly get => i switch 56 | { 57 | 0 => A1, 58 | 1 => A2, 59 | 2 => A3, 60 | 3 => A4, 61 | 4 => A5, 62 | 5 => A6, 63 | _ => throw new ArgumentOutOfRangeException(nameof(i), " Invalid Vector6 index"), 64 | }; 65 | 66 | set 67 | { 68 | switch (i) 69 | { 70 | case 0: A1 = value; break; 71 | case 1: A2 = value; break; 72 | case 2: A3 = value; break; 73 | case 3: A4 = value; break; 74 | case 4: A5 = value; break; 75 | case 5: A6 = value; break; 76 | default: 77 | throw new ArgumentOutOfRangeException(nameof(i), " Invalid Vector6 index"); 78 | } 79 | } 80 | } 81 | 82 | public readonly double[] ToArray() 83 | { 84 | return [A1, A2, A3, A4, A5, A6]; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Robots/IO/Settings.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Robots; 4 | 5 | public record Settings(string LocalLibraryPath) 6 | { 7 | /// <summary> 8 | /// Win: C:\Users\userName\AppData\Roaming\McNeel\Rhinoceros\packages\7.0\Robots\libraries 9 | /// Mac: /Users/userName/.config/McNeel/Rhinoceros/packages/7.0/Robots/libraries 10 | /// Lib: {appData}\Robots\libraries 11 | /// </summary> 12 | public static string PluginPath 13 | { 14 | get 15 | { 16 | var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.DoNotVerify); 17 | int version = 7; 18 | #if NET48 19 | version = Rhino.RhinoApp.Version.Major; 20 | #endif 21 | #if (NET48 || DEBUG) 22 | return Path.Combine(appData, "McNeel", "Rhinoceros", "packages", $"{version:0.0}", "Robots"); 23 | #elif NETSTANDARD2_0 24 | return Path.Combine(appData, "Robots"); 25 | #endif 26 | } 27 | } 28 | 29 | static string SettingsPath => Path.Combine(PluginPath, "settings.json"); 30 | 31 | static Settings GetDefault() 32 | { 33 | var localLibraryPath = 34 | Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Robots"); 35 | 36 | return new(localLibraryPath); 37 | } 38 | 39 | public static Settings Load() 40 | { 41 | if (!File.Exists(SettingsPath)) 42 | return GetDefault(); 43 | 44 | var json = File.ReadAllText(SettingsPath); 45 | var settings = JsonConvert.DeserializeObject<Settings>(json) 46 | ?? throw new(" Could not load settings file."); 47 | 48 | return settings; 49 | } 50 | 51 | public static void Save(Settings settings) 52 | { 53 | var json = JsonConvert.SerializeObject(settings, Formatting.Indented); 54 | File.WriteAllText(SettingsPath, json); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Robots/Kinematics/CustomKinematics.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | class CustomKinematics : MechanismKinematics 6 | { 7 | internal CustomKinematics(Custom custom) 8 | : base(custom) { } 9 | 10 | protected override void SetJoints(KinematicSolution solution, Target target, double[]? prevJoints) 11 | { 12 | for (int i = 0; i < _mechanism.Joints.Length; i++) 13 | { 14 | int externalNum = _mechanism.Joints[i].Number - 6; 15 | 16 | solution.Joints[i] = target.External.Length < externalNum + 1 17 | ? 0 : target.External[externalNum]; 18 | } 19 | } 20 | 21 | protected override void SetPlanes(KinematicSolution solution, Target target) 22 | { 23 | var planes = solution.Planes; 24 | 25 | for (int i = 0; i < planes.Length; i++) 26 | { 27 | planes[i] = Plane.WorldXY; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Robots/Kinematics/KinematicSolution.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public class KinematicSolution 6 | { 7 | public double[] Joints { get; internal set; } = []; 8 | public Plane[] Planes { get; internal set; } = []; 9 | public List<string> Errors { get; internal set; } = []; 10 | public RobotConfigurations Configuration { get; internal set; } 11 | 12 | public void Deconstruct(out double[] joints, out Plane[] planes, out List<string> errors, out RobotConfigurations configuration) 13 | { 14 | joints = Joints; 15 | planes = Planes; 16 | errors = Errors; 17 | configuration = Configuration; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Robots/Kinematics/PositionerKinematics.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Robots; 3 | 4 | class PositionerKinematics : MechanismKinematics 5 | { 6 | internal PositionerKinematics(Positioner positioner) 7 | : base(positioner) { } 8 | 9 | protected override void SetJoints(KinematicSolution solution, Target target, double[]? prevJoints) 10 | { 11 | for (int i = 0; i < _mechanism.Joints.Length; i++) 12 | { 13 | int externalNum = _mechanism.Joints[i].Number - 6; 14 | 15 | solution.Joints[i] = target.External.Length - 1 < externalNum 16 | ? 0 : target.External[externalNum]; 17 | } 18 | 19 | if (prevJoints is not null) 20 | solution.Joints = JointTarget.GetAbsoluteJoints(solution.Joints, prevJoints); 21 | } 22 | 23 | protected override void SetPlanes(KinematicSolution solution, Target target) 24 | { 25 | var (joints, planes, _, _) = solution; 26 | int jointCount = _mechanism.Joints.Length; 27 | 28 | for (int i = 0; i < jointCount; i++) 29 | { 30 | planes[i + 1] = _mechanism.Joints[i].Plane; 31 | for (int j = i; j >= 0; j--) 32 | planes[i + 1].Rotate(joints[j], _mechanism.Joints[j].Plane.Normal, _mechanism.Joints[j].Plane.Origin); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Robots/Kinematics/RobotCellKinematics.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | class IndustrialSystemKinematics 6 | { 7 | internal List<KinematicSolution> Solutions; 8 | 9 | internal IndustrialSystemKinematics(IndustrialSystem system, IEnumerable<Target> targets, IEnumerable<double[]>? prevJoints) 10 | { 11 | Solutions = new List<KinematicSolution>(new KinematicSolution[system.MechanicalGroups.Count]); 12 | var targetsList = targets.TryCastIList(); 13 | var prevJointsList = prevJoints?.TryCastIList(); 14 | 15 | var groupsCount = system.MechanicalGroups.Count; 16 | 17 | if (targetsList.Count != groupsCount) 18 | throw new ArgumentException(" Incorrect number of targets.", nameof(targets)); 19 | 20 | if (prevJointsList is not null && prevJointsList.Count != groupsCount) 21 | throw new ArgumentException(" Incorrect number of previous joint values.", nameof(prevJoints)); 22 | 23 | var groups = system.MechanicalGroups.ToList(); 24 | 25 | foreach (var target in targetsList) 26 | { 27 | var index = target.Frame.CoupledMechanicalGroup; 28 | if (index == -1) continue; 29 | var group = system.MechanicalGroups[index]; 30 | groups.RemoveAt(index); 31 | groups.Insert(0, group); 32 | } 33 | 34 | foreach (var group in groups) 35 | { 36 | int i = group.Index; 37 | var target = targetsList[i]; 38 | var prevJoint = prevJointsList?[i]; 39 | Plane? coupledPlane = null; 40 | 41 | int coupledGroup = target.Frame.CoupledMechanicalGroup; 42 | 43 | if (coupledGroup != -1 && target.Frame.CoupledMechanism == -1) 44 | { 45 | if (coupledGroup == i) 46 | throw new ArgumentException(" Cannot couple a robot with itself."); 47 | 48 | coupledPlane = Solutions[coupledGroup].Planes[^2]; 49 | } 50 | else 51 | { 52 | coupledPlane = null; 53 | } 54 | 55 | var kinematics = group.Kinematics(target, prevJoint, coupledPlane, system.BasePlane); 56 | Solutions[i] = kinematics; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Robots/Kinematics/TrackKinematics.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Robots; 3 | 4 | class TrackKinematics : MechanismKinematics 5 | { 6 | internal TrackKinematics(Track track) 7 | : base(track) { } 8 | 9 | protected override void SetJoints(KinematicSolution solution, Target target, double[]? prevJoints) 10 | { 11 | for (int i = 0; i < _mechanism.Joints.Length; i++) 12 | { 13 | int externalNum = _mechanism.Joints[i].Number - 6; 14 | 15 | solution.Joints[i] = target.External.Length < externalNum + 1 16 | ? 0 : target.External[externalNum]; 17 | } 18 | } 19 | 20 | protected override void SetPlanes(KinematicSolution solution, Target target) 21 | { 22 | var (joints, planes, _, _) = solution; 23 | 24 | planes[1] = _mechanism.Joints[0].Plane; 25 | planes[1].Origin += planes[1].XAxis * joints[0]; 26 | 27 | if (_mechanism.Joints.Length == 1) 28 | return; 29 | 30 | planes[2] = _mechanism.Joints[1].Plane; 31 | planes[2].Origin += planes[1].Origin + planes[2].YAxis * joints[1]; 32 | 33 | if (_mechanism.Joints.Length == 2) 34 | return; 35 | 36 | planes[3] = _mechanism.Joints[2].Plane; 37 | planes[3].Origin += planes[2].Origin + planes[3].ZAxis * joints[2]; 38 | 39 | if (_mechanism.Joints.Length == 3) 40 | return; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Robots/Mechanisms/Custom.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public class Custom : Mechanism 6 | { 7 | internal Custom(string model, Manufacturers manufacturer, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints, bool movesRobot) 8 | : base(model, manufacturer, payload, basePlane, baseMesh, joints, movesRobot) { } 9 | 10 | protected override void SetStartPlanes() 11 | { 12 | var plane = Plane.WorldXY; 13 | 14 | foreach (var joint in Joints) 15 | joint.Plane = plane; 16 | } 17 | 18 | private protected override MechanismKinematics CreateSolver() => new CustomKinematics(this); 19 | public override double DegreeToRadian(double degree, int i) => degree; 20 | public override double RadianToDegree(double radian, int i) => radian; 21 | } 22 | -------------------------------------------------------------------------------- /src/Robots/Mechanisms/Joints.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public abstract class Joint 6 | { 7 | public int Index { get; set; } 8 | public int Number { get; set; } 9 | internal double A { get; set; } 10 | internal double D { get; set; } 11 | internal double Alpha { get; set; } 12 | internal double Theta { get; set; } 13 | internal int Sign { get; set; } 14 | public Interval Range { get; internal set; } 15 | public double MaxSpeed { get; internal set; } 16 | public Plane Plane { get; set; } 17 | public Mesh Mesh { get; set; } = default!; 18 | } 19 | 20 | public class BaseJoint 21 | { 22 | } 23 | 24 | public class RevoluteJoint : Joint 25 | { 26 | } 27 | 28 | public class PrismaticJoint : Joint 29 | { 30 | } 31 | -------------------------------------------------------------------------------- /src/Robots/Mechanisms/Positioner.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static System.Math; 3 | 4 | namespace Robots; 5 | 6 | public class Positioner : Mechanism 7 | { 8 | internal Positioner(string model, Manufacturers manufacturer, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints, bool movesRobot) 9 | : base(model, manufacturer, payload, basePlane, baseMesh, joints, movesRobot) { } 10 | 11 | protected override void SetStartPlanes() 12 | { 13 | if (Joints.Length == 1) 14 | { 15 | Joints[0].Plane = new Plane(new Point3d(Joints[0].A, 0, Joints[0].D), Vector3d.XAxis, Vector3d.YAxis); 16 | } 17 | else 18 | { 19 | Joints[0].Plane = new Plane(new Point3d(0, 0, Joints[0].D), Vector3d.XAxis, Vector3d.ZAxis); 20 | Joints[1].Plane = new Plane(new Point3d(0, Joints[1].A, Joints[0].D + Joints[1].D), Vector3d.XAxis, Vector3d.YAxis); 21 | } 22 | } 23 | 24 | private protected override MechanismKinematics CreateSolver() => new PositionerKinematics(this); 25 | 26 | public override double DegreeToRadian(double degree, int i) => degree * (PI / 180); 27 | public override double RadianToDegree(double radian, int i) => radian * (180 / PI); 28 | } 29 | -------------------------------------------------------------------------------- /src/Robots/Mechanisms/Track.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public class Track : Mechanism 6 | { 7 | internal Track(string model, Manufacturers manufacturer, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints, bool movesRobot) 8 | : base(model, manufacturer, payload, basePlane, baseMesh, joints, movesRobot) { } 9 | 10 | protected override void SetStartPlanes() 11 | { 12 | var plane = Plane.WorldXY; 13 | foreach (var joint in Joints) 14 | { 15 | plane.Origin = plane.Origin + plane.XAxis * joint.A + plane.ZAxis * joint.D; 16 | joint.Plane = plane; 17 | } 18 | 19 | /* 20 | if (Joints.Length == 3) 21 | { 22 | plane = Joints[2].Plane; 23 | plane.Rotate(PI, plane.XAxis); 24 | Joints[2].Plane = plane; 25 | } 26 | */ 27 | } 28 | 29 | private protected override MechanismKinematics CreateSolver() => new TrackKinematics(this); 30 | public override double DegreeToRadian(double degree, int i) => degree; 31 | public override double RadianToDegree(double radian, int i) => radian; 32 | } 33 | -------------------------------------------------------------------------------- /src/Robots/Program/CellTarget.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public class SystemTarget 6 | { 7 | public List<ProgramTarget> ProgramTargets { get; internal set; } 8 | public int Index { get; internal set; } 9 | public double TotalTime { get; internal set; } 10 | public double DeltaTime { get; internal set; } 11 | internal double MinTime { get; set; } 12 | 13 | public Plane[] Planes => ProgramTargets.SelectMany(x => x.Kinematics.Planes).ToArray(); 14 | public double[] Joints => ProgramTargets.SelectMany(x => x.Kinematics.Joints).ToArray(); 15 | 16 | internal SystemTarget(List<ProgramTarget> programTargets, int index) 17 | { 18 | foreach (var programTarget in programTargets) 19 | programTarget.SystemTarget = this; 20 | 21 | ProgramTargets = programTargets; 22 | Index = index; 23 | } 24 | 25 | internal SystemTarget ShallowClone(int index = -1) 26 | { 27 | var systemTarget = (SystemTarget)MemberwiseClone(); 28 | 29 | if (index != -1) 30 | systemTarget.Index = index; 31 | 32 | systemTarget.ProgramTargets = systemTarget.ProgramTargets.MapToList(x => x.ShallowClone(systemTarget)); 33 | return systemTarget; 34 | } 35 | 36 | internal IEnumerable<Target> Lerp(SystemTarget prevTarget, RobotSystem robot, double t, double start, double end) 37 | { 38 | return ProgramTargets.Select((x, i) => x.Lerp(prevTarget.ProgramTargets[i], robot, t, start, end)); 39 | } 40 | 41 | internal void SetTargetKinematics(List<KinematicSolution> kinematics, List<string> errors, List<string> warnings, SystemTarget? prevTarget = null) 42 | { 43 | foreach (var target in ProgramTargets) 44 | target.SetTargetKinematics(kinematics[target.Group], errors, warnings, prevTarget?.ProgramTargets[target.Group]); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Robots/Program/CustomProgram.cs: -------------------------------------------------------------------------------- 1 | namespace Robots; 2 | 3 | public class CustomProgram(string name, RobotSystem robotSystem, List<int> multiFileIndices, List<List<List<string>>> code) : IProgram 4 | { 5 | public string Name { get; } = name; 6 | public RobotSystem RobotSystem { get; } = robotSystem; 7 | public List<List<List<string>>>? Code { get; } = code; 8 | public List<int> MultiFileIndices { get; } = multiFileIndices; 9 | public bool HasSimulation => false; 10 | 11 | public void Save(string folder) => RobotSystem.SaveCode(this, folder); 12 | 13 | public override string ToString() => $"Program ({Name} with custom code)"; 14 | } 15 | -------------------------------------------------------------------------------- /src/Robots/Remotes/Ftp.cs: -------------------------------------------------------------------------------- 1 | using Renci.SshNet; 2 | 3 | namespace Robots; 4 | 5 | class Ftp 6 | { 7 | public static void Upload(byte[] bytes, string fileName, User user) 8 | { 9 | var (ip, username, password, programsDir) = user; 10 | 11 | ConnectionInfo connectionInfo = new(ip, username, new PasswordAuthenticationMethod(username, password)) 12 | { 13 | Timeout = TimeSpan.FromSeconds(5) 14 | }; 15 | 16 | // Remove ecdsa algorithms not supported in mono (MacOS) 17 | // https://github.com/sshnet/SSH.NET/issues/807 18 | var algsToRemove = connectionInfo.HostKeyAlgorithms.Keys 19 | .Where(algName => algName.StartsWith("ecdsa")) 20 | .ToList(); 21 | 22 | foreach (var algName in algsToRemove) 23 | connectionInfo.HostKeyAlgorithms.Remove(algName); 24 | 25 | using SftpClient client = new(connectionInfo); 26 | client.Connect(); 27 | 28 | if (!client.Exists(programsDir)) 29 | throw new DirectoryNotFoundException($"\"{programsDir}\" folder not found."); 30 | 31 | using MemoryStream stream = new(bytes); 32 | string filePath = $"{programsDir}/{fileName}"; 33 | client.UploadFile(stream, filePath, true); 34 | client.Disconnect(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Robots/Remotes/IRemote.cs: -------------------------------------------------------------------------------- 1 | namespace Robots; 2 | 3 | public interface IRemote 4 | { 5 | List<string> Log { get; } 6 | string? IP { get; set; } 7 | void Upload(IProgram program); 8 | void Pause(); 9 | void Play(); 10 | } 11 | -------------------------------------------------------------------------------- /src/Robots/Remotes/RemoteUR.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Robots; 3 | 4 | interface IRemoteURBackend 5 | { 6 | void Upload(IProgram program); 7 | void Pause(); 8 | void Play(); 9 | void Send(string message); 10 | } 11 | 12 | public class RemoteUR : IRemote 13 | { 14 | IRemoteURBackend? _backend; 15 | 16 | public string? IP 17 | { 18 | get => throw new NotImplementedException(); 19 | set 20 | { 21 | if (value is null) 22 | return; 23 | 24 | try 25 | { 26 | var user = new User(value); 27 | _backend = new RemoteURFtp(user, AddLog); 28 | } 29 | catch 30 | { 31 | _backend = new RemoteURSecondaryClient(value, AddLog); 32 | } 33 | } 34 | } 35 | 36 | public List<string> Log { get; } = []; 37 | 38 | public void Pause() 39 | { 40 | CheckIP(); 41 | _backend?.Pause(); 42 | } 43 | 44 | public void Play() 45 | { 46 | CheckIP(); 47 | _backend?.Play(); 48 | } 49 | 50 | public void Upload(IProgram program) 51 | { 52 | CheckIP(); 53 | _backend?.Upload(program); 54 | } 55 | public void Send(string message) 56 | { 57 | CheckIP(); 58 | _backend?.Send(message); 59 | } 60 | 61 | void CheckIP() 62 | { 63 | if (_backend is null) 64 | AddLog("Error: IP not set."); 65 | } 66 | 67 | void AddLog(string text) 68 | { 69 | Log.Insert(0, $"{DateTime.Now.ToLongTimeString()} - {text}"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Robots/Remotes/RemoteURFtp.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Sockets; 2 | using System.Text; 3 | 4 | namespace Robots; 5 | 6 | class RemoteURFtp(User user, Action<string> log) : IRemoteURBackend 7 | { 8 | const int _dashboardPort = 29999; 9 | readonly Action<string> _log = log; 10 | readonly User _user = user; 11 | 12 | public void Upload(IProgram program) 13 | { 14 | try 15 | { 16 | UploadFtp(program); 17 | } 18 | catch (Exception e) 19 | { 20 | AddLog($"Error: FTP - {e}"); 21 | return; 22 | } 23 | 24 | Send($"load {_user.ProgramsDir}/{program.Name}.urp"); 25 | } 26 | 27 | public void Pause() => Send("pause"); 28 | public void Play() => Send("play"); 29 | 30 | public void Send(string message) 31 | { 32 | try 33 | { 34 | SendPrivate(message); 35 | } 36 | catch (Exception e) 37 | { 38 | AddLog($"Error: {e.Message}"); 39 | } 40 | } 41 | 42 | void SendPrivate(string message) 43 | { 44 | using var client = new TcpClient(); 45 | client.Connect(_user.IP, _dashboardPort); 46 | 47 | using var stream = client.GetStream(); 48 | string first = GetMessage(stream); 49 | 50 | byte[] sendBuffer = Encoding.ASCII.GetBytes(message + '\n'); 51 | stream.Write(sendBuffer, 0, sendBuffer.Length); 52 | //AddLog($"Sent: {message}"); 53 | 54 | string second = GetMessage(stream); 55 | AddLog($"Received: {second}"); 56 | 57 | static string GetMessage(NetworkStream stream) 58 | { 59 | byte[] receiveBuffer = new byte[1024]; 60 | int bytesReceived = stream.Read(receiveBuffer, 0, receiveBuffer.Length); 61 | string data = Encoding.UTF8.GetString(receiveBuffer, 0, bytesReceived); 62 | return data; 63 | } 64 | } 65 | 66 | void UploadFtp(IProgram program) 67 | { 68 | var urp = SystemUR.CreateUrp(program); 69 | var bytes = Encoding.ASCII.GetBytes(urp); 70 | string fileName = $"{program.Name}.urp"; 71 | 72 | Ftp.Upload(bytes, fileName, _user); 73 | } 74 | 75 | void AddLog(string message) => _log(message); 76 | } 77 | -------------------------------------------------------------------------------- /src/Robots/Remotes/RemoteURPrimaryClient.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Sockets; 2 | using System.Text; 3 | 4 | namespace Robots; 5 | 6 | class RemoteURSecondaryClient(string ip, Action<string> log) : IRemoteURBackend 7 | { 8 | const int _secondaryPort = 30002; 9 | readonly string _ip = ip; 10 | readonly Action<string> _log = log; 11 | 12 | public void Upload(IProgram program) 13 | { 14 | if (program.Code is null) 15 | { 16 | AddLog("Error: Program code not generated."); 17 | return; 18 | } 19 | 20 | var joinedCode = string.Join("\n", program.Code[0][0]); 21 | Send(joinedCode); 22 | } 23 | 24 | public void Pause() => Send("pause program"); 25 | public void Play() => Send("resume program"); 26 | 27 | public void Send(string message) 28 | { 29 | try 30 | { 31 | SendPrivate(message); 32 | } 33 | catch (Exception e) 34 | { 35 | AddLog($"Error: {e.Message}"); 36 | } 37 | } 38 | 39 | void SendPrivate(string message) 40 | { 41 | using var client = new TcpClient(); 42 | client.Connect(_ip, _secondaryPort); 43 | 44 | using var stream = client.GetStream(); 45 | message += '\n'; 46 | byte[] sendBuffer = Encoding.ASCII.GetBytes(message); 47 | 48 | stream.Write(sendBuffer, 0, sendBuffer.Length); 49 | 50 | string firstLine = message[..message.IndexOf('\n')]; 51 | string text = firstLine.Length + 1 < message.Length 52 | ? "Robot program" : message; 53 | 54 | AddLog($"Sending: {text}"); 55 | } 56 | 57 | void AddLog(string message) => _log(message); 58 | } 59 | -------------------------------------------------------------------------------- /src/Robots/Remotes/User.cs: -------------------------------------------------------------------------------- 1 | namespace Robots; 2 | 3 | class User 4 | { 5 | public string IP { get; set; } = ""; 6 | public string Username { get; set; } = "root"; 7 | public string Password { get; set; } = "easybot"; 8 | public string ProgramsDir { get; set; } = "/programs"; 9 | 10 | public User(string? ip) 11 | { 12 | if (ip is null) 13 | throw new ArgumentNullException(nameof(ip)); 14 | 15 | Uri uri = new(ip); 16 | IP = uri.Host; 17 | 18 | if (!string.IsNullOrWhiteSpace(uri.UserInfo)) 19 | { 20 | var split = uri.UserInfo.Split(':'); 21 | 22 | if (split is not null && split.Length == 2) 23 | { 24 | Username = split[0]; 25 | Password = split[1]; 26 | } 27 | } 28 | 29 | if (!string.IsNullOrWhiteSpace(uri.PathAndQuery) && uri.PathAndQuery != "/") 30 | ProgramsDir = uri.PathAndQuery; 31 | } 32 | 33 | public void Deconstruct(out string ip, out string username, out string password, out string programsDir) 34 | { 35 | ip = IP; 36 | username = Username; 37 | password = Password; 38 | programsDir = ProgramsDir; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Robots/Resources/URRTDE.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visose/Robots/3becdb8f87ed174c04dfb9c6447693b5c57384a0/src/Robots/Resources/URRTDE.csv -------------------------------------------------------------------------------- /src/Robots/Resources/URRealTime.csv: -------------------------------------------------------------------------------- 1 | Message Size,integer,1,4,,Total message length in bytes,,,,,,,,,,,, 2 | Time,double,1,8,1,Time elapsed since the controller was started,,,,,,,,,,,, 3 | q target,double,6,48,2 - 7,Target joint positions,,,,,,,,,,,, 4 | qd target,double,6,48,8 - 13,Target joint velocities,,,,,,,,,,,, 5 | qdd target,double,6,48,14 - 19,Target joint accelerations,,,,,,,,,,,, 6 | I target,double,6,48,20 - 25,Target joint currents,,,,,,,,,,,, 7 | M target,double,6,48,26 - 31,Target joint moments (torques),,,,,,,,,,,, 8 | q actual,double,6,48,32 - 37,Actual joint positions,,,,,,,,,,,, 9 | qd actual,double,6,48,38 - 43,Actual joint velocities,,,,,,,,,,,, 10 | I actual,double,6,48,44 - 49,Actual joint currents,,,,,,,,,,,, 11 | Tool Accelerometer values,double,3,24,50 - 53,"Tool x,y and z accelerometer values (software version 1.7)",,,,,,,,,,,, 12 | Unused,double,15,120,54 - 67,Unused,,,,,,,,,,,, 13 | TCP force,double,6,48,68 - 73,Generalised forces in the TCP,,,,,,,,,,,, 14 | Tool vector,double,6,48,74 - 79,"Cartesian coordinates of the tool: (x,y,z,rx,ry,rz), where rx, ry and rz is a rotation vector representation of the tool orientation",,,,,,,,,,,, 15 | TCP speed,double,6,48,80 - 85,Speed of the tool given in cartesian coordinates,,,,,,,,,,,, 16 | Digital input bits,double,1,8,86,"Current state of the digital inputs. NOTE: these are bits encoded as int64_t, e.g. a value of 5 corresponds to bit 0 and bit 2 set high",,,,,,,,,,,, 17 | Motor temperatures,double,6,48,87 - 92,Temperature of each joint in degrees celcius,,,,,,,,,,,, 18 | Controller Timer,double,1,8,93,Controller realtime thread execution time,,,,,,,,,,,, 19 | Test value,double,1,8,94,A value used by Universal Robots software only,,,,,,,,,,,, 20 | Robot Mode,double,1,8,95,"Robot control mode (see PolyScopeProgramServer on the ""How to"" page",,,,,,,,,,,, 21 | Joint Modes,double,6,48,96-101,"Joint control modes (see PolyScopeProgramServer on the ""How to"" page) (only from software version 1.8 and on)",,,,,,,,,,,, -------------------------------------------------------------------------------- /src/Robots/Resources/UrpTemplate.txt: -------------------------------------------------------------------------------- 1 | <URProgram name="{Name}" installation="default" installationRelativePath="default" createdIn="{Version}" lastSavedIn="{Version}"> 2 | <children> 3 | <MainProgram runOnlyOnce="true" InitVariablesNode="false"> 4 | <children> 5 | <Script type="File"> 6 | <cachedContents>{Code} 7 | Program() 8 | </cachedContents> 9 | <file>{File}</file> 10 | </Script> 11 | </children> 12 | </MainProgram> 13 | </children> 14 | </URProgram> -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotAbb.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static System.Math; 3 | using static Robots.Util; 4 | 5 | namespace Robots; 6 | 7 | public class RobotAbb : RobotArm 8 | { 9 | internal RobotAbb(string model, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 10 | : base(model, Manufacturers.ABB, payload, basePlane, baseMesh, joints) { } 11 | 12 | private protected override MechanismKinematics CreateSolver() 13 | { 14 | var isNumerical = Model.StartsWith("ABB.CRB15000", StringComparison.OrdinalIgnoreCase); 15 | 16 | return isNumerical 17 | ? new NumericalKinematics(this) 18 | : new SphericalWristKinematics(this); 19 | } 20 | 21 | public static double ABBDegreeToRadian(double degree, int i) 22 | { 23 | double radian = degree.ToRadians(); 24 | if (i == 1) radian = -radian + PI * 0.5; 25 | if (i == 2) radian *= -1; 26 | if (i == 4) radian *= -1; 27 | return radian; 28 | } 29 | 30 | public override double DegreeToRadian(double degree, int i) 31 | { 32 | return ABBDegreeToRadian(degree, i); 33 | } 34 | 35 | public override double RadianToDegree(double radian, int i) 36 | { 37 | if (i == 1) { radian -= PI * 0.5; radian = -radian; } 38 | if (i == 2) radian *= -1; 39 | if (i == 4) radian *= -1; 40 | return radian.ToDegrees(); 41 | } 42 | 43 | protected override double[] DefaultAlpha => [HalfPI, 0, HalfPI, -HalfPI, HalfPI, 0]; 44 | protected override double[] DefaultTheta => [0, HalfPI, 0, 0, 0, 0]; 45 | protected override int[] DefaultSign => [1, -1, -1, 1, -1, 1]; 46 | } 47 | -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotArm.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public abstract class RobotArm : Mechanism 6 | { 7 | internal RobotArm(string model, Manufacturers manufactuer, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 8 | : base(model, manufactuer, payload, basePlane, baseMesh, joints, false) { } 9 | 10 | protected override void SetStartPlanes() 11 | { 12 | var thetas = Joints.Map(j => j.Theta); 13 | var startPose = new JointTarget(thetas); 14 | var kinematics = Kinematics(startPose); 15 | 16 | for (int i = 0; i < Joints.Length; i++) 17 | { 18 | Plane plane = kinematics.Planes[i + 1]; 19 | plane.InverseOrient(ref BasePlane); 20 | Joints[i].Plane = plane; 21 | } 22 | } 23 | 24 | protected abstract override double[]? DefaultAlpha { get; } 25 | } 26 | -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotDoosan.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static System.Math; 3 | using static Robots.Util; 4 | 5 | namespace Robots; 6 | 7 | public class RobotDoosan : RobotArm 8 | { 9 | internal RobotDoosan(string model, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 10 | : base(model, Manufacturers.Doosan, payload, basePlane, baseMesh, joints) { } 11 | 12 | private protected override MechanismKinematics CreateSolver() => new SphericalWristKinematics(this); 13 | 14 | public override double DegreeToRadian(double degree, int i) 15 | { 16 | var radian = degree.ToRadians(); 17 | if (i == 0) radian -= PI; 18 | return (radian + Joints[i].Theta); 19 | } 20 | 21 | public override double RadianToDegree(double radian, int i) 22 | { 23 | if (i == 0) radian += PI; 24 | return (radian - Joints[i].Theta) * (180.0 / PI); 25 | } 26 | 27 | protected override double[] DefaultAlpha => [HalfPI, 0, HalfPI, -HalfPI, HalfPI, 0]; 28 | protected override double[] DefaultTheta => [0, HalfPI, HalfPI, 0, 0, PI]; 29 | protected override int[] DefaultSign => [1, 1, 1, 1, 1, 1]; 30 | } 31 | -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotFanuc.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static System.Math; 3 | using static Robots.Util; 4 | 5 | namespace Robots; 6 | 7 | public class RobotFanuc : RobotArm 8 | { 9 | internal RobotFanuc(string model, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 10 | : base(model, Manufacturers.Fanuc, payload, basePlane, baseMesh, joints) { } 11 | private protected override MechanismKinematics CreateSolver() => new SphericalWristKinematics(this); 12 | 13 | public static double FanucDegreeToRadian(double degree, int i) 14 | { 15 | double radian = degree.ToRadians(); 16 | if (i == 1) radian = -radian + PI * 0.5; 17 | if (i == 3) radian *= -1; 18 | if (i == 5) radian *= -1; 19 | return radian; 20 | } 21 | 22 | public override double DegreeToRadian(double degree, int i) 23 | { 24 | return FanucDegreeToRadian(degree, i); 25 | } 26 | 27 | public override double RadianToDegree(double radian, int i) 28 | { 29 | if (i == 1) { radian -= PI * 0.5; radian = -radian; } 30 | if (i == 3) radian *= -1; 31 | if (i == 5) radian *= -1; 32 | return radian.ToDegrees(); 33 | } 34 | 35 | protected override double[] DefaultAlpha => [HalfPI, 0, HalfPI, -HalfPI, HalfPI, 0]; 36 | protected override double[] DefaultTheta => [0, HalfPI, 0, 0, 0, 0]; 37 | protected override int[] DefaultSign => [1, -1, -1, 1, -1, 1]; 38 | } 39 | -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotFranka.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static System.Math; 3 | using static Robots.Util; 4 | 5 | namespace Robots; 6 | 7 | public class RobotFranka : RobotArm 8 | { 9 | internal RobotFranka(string model, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 10 | : base(model, Manufacturers.UR, payload, basePlane, baseMesh, joints) { } 11 | 12 | private protected override MechanismKinematics CreateSolver() 13 | { 14 | return new NumericalKinematics(this, true, 2); 15 | } 16 | 17 | public override double DegreeToRadian(double degree, int i) => degree * (PI / 180.0); 18 | public override double RadianToDegree(double radian, int i) => radian * (180.0 / PI); 19 | 20 | protected override double[] DefaultAlpha => [0, -HalfPI, HalfPI, HalfPI, -HalfPI, HalfPI, HalfPI]; 21 | protected override double[] DefaultTheta => [0.0, 0, 0, 0, 0, 0, 0]; 22 | protected override int[] DefaultSign => [1, 1, 1, 1, 1, 1, 1]; 23 | } 24 | -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotIgus.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static System.Math; 3 | using static Robots.Util; 4 | 5 | namespace Robots; 6 | 7 | public class RobotIgus : RobotArm 8 | { 9 | internal RobotIgus(string model, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 10 | : base(model, Manufacturers.Igus, payload, basePlane, baseMesh, joints) { } 11 | 12 | private protected override MechanismKinematics CreateSolver() => new SphericalWristKinematics(this); 13 | 14 | public override double DegreeToRadian(double degree, int i) 15 | { 16 | double radian = degree.ToRadians(); 17 | 18 | if (i == 1 || i == 2) 19 | radian -= HalfPI; 20 | 21 | radian = -radian; 22 | return radian; 23 | } 24 | 25 | public override double RadianToDegree(double radian, int i) 26 | { 27 | if (i != 0 && i != 5) 28 | radian = -radian; 29 | 30 | if (i == 1 || i == 2) 31 | radian += HalfPI; 32 | 33 | return radian.ToDegrees(); 34 | } 35 | 36 | protected override double[] DefaultAlpha => [HalfPI, 0, HalfPI, -HalfPI, HalfPI, 0]; 37 | protected override double[] DefaultTheta => [0, HalfPI, HalfPI, 0, 0, -PI]; 38 | protected override int[] DefaultSign => [-1, -1, -1, -1, -1, -1]; 39 | } 40 | -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotJaka.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static Robots.Util; 3 | 4 | namespace Robots; 5 | 6 | public class RobotJaka : RobotArm 7 | { 8 | internal RobotJaka(string model, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 9 | : base(model, Manufacturers.Jaka, payload, basePlane, baseMesh, joints) { } 10 | 11 | private protected override MechanismKinematics CreateSolver() => new SphericalWristKinematics(this); 12 | 13 | public override double DegreeToRadian(double degree, int i) 14 | { 15 | double radian = degree.ToRadians(); 16 | if (i == 1) radian = -radian + HalfPI; 17 | if (i == 2) radian *= -1; 18 | if (i == 2) radian += HalfPI; 19 | if (i == 4) radian *= -1; 20 | return radian; 21 | } 22 | 23 | public override double RadianToDegree(double radian, int i) 24 | { 25 | if (i == 1) { radian -= HalfPI; radian = -radian; } 26 | if (i == 2) radian -= HalfPI; 27 | if (i == 2) radian *= -1; 28 | if (i == 4) radian *= -1; 29 | return radian.ToDegrees(); 30 | } 31 | 32 | protected override double[] DefaultAlpha => [HalfPI, 0, HalfPI, -HalfPI, HalfPI, 0]; 33 | protected override double[] DefaultTheta => [0, HalfPI, HalfPI, 0, 0, 0]; 34 | protected override int[] DefaultSign => [1, -1, -1, 1, -1, 1]; 35 | } 36 | -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotKuka.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static System.Math; 3 | using static Robots.Util; 4 | 5 | namespace Robots; 6 | 7 | public class RobotKuka : RobotArm 8 | { 9 | internal RobotKuka(string model, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 10 | : base(model, Manufacturers.KUKA, payload, basePlane, baseMesh, joints) { } 11 | 12 | private protected override MechanismKinematics CreateSolver() => new SphericalWristKinematics(this); 13 | 14 | public override double DegreeToRadian(double degree, int i) 15 | { 16 | double radian = degree.ToRadians(); 17 | if (i == 2) radian -= HalfPI; 18 | radian = -radian; 19 | return radian; 20 | } 21 | 22 | public override double RadianToDegree(double radian, int i) 23 | { 24 | radian = -radian; 25 | if (i == 2) radian += HalfPI; 26 | return radian.ToDegrees(); 27 | } 28 | 29 | protected override double[] DefaultAlpha => [HalfPI, 0, HalfPI, -HalfPI, HalfPI, 0]; 30 | protected override double[] DefaultTheta => [0, HalfPI, 0, 0, 0, -PI]; 31 | protected override int[] DefaultSign => [-1, -1, -1, -1, -1, -1]; 32 | } 33 | -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotStaubli.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static Robots.Util; 3 | 4 | namespace Robots; 5 | 6 | public class RobotStaubli : RobotArm 7 | { 8 | internal RobotStaubli(string model, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 9 | : base(model, Manufacturers.Staubli, payload, basePlane, baseMesh, joints) { } 10 | 11 | private protected override MechanismKinematics CreateSolver() => new SphericalWristKinematics(this); 12 | 13 | public override double DegreeToRadian(double degree, int i) 14 | { 15 | double radian = degree.ToRadians(); 16 | if (i == 1) radian = -radian + HalfPI; 17 | if (i == 2) radian *= -1; 18 | if (i == 2) radian += HalfPI; 19 | if (i == 4) radian *= -1; 20 | return radian; 21 | } 22 | 23 | public override double RadianToDegree(double radian, int i) 24 | { 25 | if (i == 1) { radian -= HalfPI; radian = -radian; } 26 | if (i == 2) radian -= HalfPI; 27 | if (i == 2) radian *= -1; 28 | if (i == 4) radian *= -1; 29 | return radian.ToDegrees(); 30 | } 31 | 32 | protected override double[] DefaultAlpha => [HalfPI, 0, HalfPI, -HalfPI, HalfPI, 0]; 33 | protected override double[] DefaultTheta => [0, HalfPI, HalfPI, 0, 0, 0]; 34 | protected override int[] DefaultSign => [1, -1, -1, 1, -1, 1]; 35 | } 36 | -------------------------------------------------------------------------------- /src/Robots/RobotArms/RobotUR.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | using static System.Math; 3 | using static Robots.Util; 4 | 5 | namespace Robots; 6 | 7 | public class RobotUR : RobotArm 8 | { 9 | internal RobotUR(string model, double payload, Plane basePlane, Mesh baseMesh, Joint[] joints) 10 | : base(model, Manufacturers.UR, payload, basePlane, baseMesh, joints) { } 11 | 12 | private protected override MechanismKinematics CreateSolver() => new OffsetWristKinematics(this); 13 | public override double DegreeToRadian(double degree, int i) => degree * (PI / 180.0); 14 | public override double RadianToDegree(double radian, int i) => radian * (180.0 / PI); 15 | protected override double[] DefaultAlpha => [HalfPI, 0, 0, HalfPI, -HalfPI, 0]; 16 | protected override double[] DefaultTheta => [0, -HalfPI, 0, -HalfPI, 0, 0]; 17 | protected override int[] DefaultSign => [1, 1, 1, 1, 1, 1]; 18 | } 19 | -------------------------------------------------------------------------------- /src/Robots/RobotSystems/CobotSystem.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public abstract class CobotSystem : RobotSystem 6 | { 7 | public RobotArm Robot { get; } 8 | 9 | internal CobotSystem(SystemAttributes attributes, RobotArm robot) 10 | : base(attributes, GetDefaultPose(robot)) 11 | { 12 | Robot = robot; 13 | DisplayMesh.Append(robot.DisplayMesh); 14 | DisplayMesh.Transform(BasePlane.ToTransform()); 15 | } 16 | 17 | static DefaultPose GetDefaultPose(RobotArm robot) 18 | { 19 | return new DefaultPose( 20 | [robot.Joints.Select(j => j.Plane).Prepend(Plane.WorldXY).ToList()], 21 | [robot.Joints.Select(j => j.Mesh).Prepend(robot.BaseMesh).ToList()] 22 | ); 23 | } 24 | 25 | public override double DegreeToRadian(double degree, int i, int group = 0) 26 | { 27 | return Robot.DegreeToRadian(degree, i); 28 | } 29 | 30 | internal override double Payload(int group) 31 | { 32 | return Robot.Payload; 33 | } 34 | 35 | internal override IList<Joint> GetJoints(int group) 36 | { 37 | return Robot.Joints; 38 | } 39 | 40 | public override List<KinematicSolution> Kinematics(IEnumerable<Target> target, IEnumerable<double[]?>? prevJoints = null) 41 | { 42 | if (!target.Any()) 43 | return []; 44 | 45 | var singleTarget = target.First(); 46 | var prevJoint = prevJoints?.First(); 47 | string? error = null; 48 | 49 | if (prevJoint is not null && prevJoint.Length != RobotJointCount) 50 | { 51 | error = $"Previous joints set but contain {prevJoint.Length} value(s), should contain {RobotJointCount} values."; 52 | prevJoint = null; 53 | } 54 | 55 | var kinematic = Robot.Kinematics(singleTarget, prevJoint, BasePlane); 56 | var planes = kinematic.Planes.ToList(); 57 | 58 | // Tool 59 | if (singleTarget.Tool is not null) 60 | { 61 | Plane toolPlane = singleTarget.Tool.Tcp; 62 | toolPlane.Orient(ref kinematic.Planes[planes.Count - 1]); 63 | planes.Add(toolPlane); 64 | } 65 | else 66 | { 67 | planes.Add(planes[^1]); 68 | } 69 | 70 | kinematic.Planes = [.. planes]; 71 | 72 | if (error is not null) 73 | kinematic.Errors.Add(error); 74 | 75 | return [kinematic]; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Robots/RobotSystems/IO.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Robots; 3 | 4 | public class IO(Manufacturers manufacturer, bool useControllerNumbering, string[] @do, string[] di, string[] ao, string[] ai) 5 | { 6 | private readonly Manufacturers _manufacturer = manufacturer; 7 | public string[] DO { get; } = @do; 8 | public string[] DI { get; } = di; 9 | public string[] AO { get; } = ao; 10 | public string[] AI { get; } = ai; 11 | public bool UseControllerNumbering { get; } = useControllerNumbering; 12 | 13 | internal void CheckBounds(int index, string[] array) 14 | { 15 | if (UseControllerNumbering) 16 | { 17 | if (index < GetStartIndex()) 18 | throw new ArgumentOutOfRangeException(nameof(index), " Index of IO is out of range."); 19 | 20 | return; 21 | } 22 | 23 | if (index < 0 || index >= array.Length) 24 | throw new ArgumentOutOfRangeException(nameof(index), " Index of IO is out of range."); 25 | } 26 | 27 | int GetStartIndex() => _manufacturer switch 28 | { 29 | Manufacturers.ABB => 1, 30 | Manufacturers.KUKA => 1, 31 | _ => 0 32 | }; 33 | } -------------------------------------------------------------------------------- /src/Robots/RobotSystems/SystemFranka.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public class SystemFranka : CobotSystem 6 | { 7 | internal SystemFranka(SystemAttributes attributes, RobotFranka robot) 8 | : base(attributes, robot) 9 | { 10 | Remote = new RemoteFranka(); 11 | } 12 | 13 | public override int RobotJointCount => 7; 14 | public override Manufacturers Manufacturer => Manufacturers.FrankaEmika; 15 | protected override IPostProcessor GetDefaultPostprocessor() => new FrankxPostProcessor(); 16 | 17 | static Plane QuaternionToPlane(double x, double y, double z, double q1, double q2, double q3, double q4) 18 | { 19 | var point = new Point3d(x, y, z); 20 | var quaternion = new Quaternion(q1, q2, q3, q4); 21 | return quaternion.ToPlane(point); 22 | } 23 | 24 | public override double[] PlaneToNumbers(Plane plane) 25 | { 26 | var q = plane.ToQuaternion(); 27 | var origin = plane.Origin.ToMeters(); 28 | return [origin.X, origin.Y, origin.Z, q.A, q.B, q.C, q.D]; 29 | } 30 | 31 | public override Plane NumbersToPlane(double[] numbers) 32 | { 33 | double n0 = numbers[0].FromMeters(); 34 | double n1 = numbers[1].FromMeters(); 35 | double n2 = numbers[2].FromMeters(); 36 | 37 | return QuaternionToPlane(n0, n1, n2, numbers[3], numbers[4], numbers[5], numbers[6]); 38 | } 39 | 40 | internal override void SaveCode(IProgram program, string folder) 41 | { 42 | if (program.Code is null) 43 | throw new InvalidOperationException(" Program code not generated"); 44 | 45 | string filePath = Path.Combine(folder, $"{program.Name}.py"); 46 | var code = program.Code[0][0]; 47 | var joinedCode = string.Join("\r\n", code); 48 | File.WriteAllText(filePath, joinedCode); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Robots/RobotSystems/SystemJaka.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Rhino.Geometry; 3 | 4 | namespace Robots; 5 | 6 | public class SystemJaka : IndustrialSystem 7 | { 8 | internal SystemJaka(SystemAttributes attributes, List<MechanicalGroup> mechanicalGroups) 9 | : base(attributes, mechanicalGroups) 10 | { 11 | } 12 | 13 | public override Manufacturers Manufacturer => Manufacturers.Jaka; 14 | protected override IPostProcessor GetDefaultPostprocessor() => new JKSPostProcessor(); 15 | 16 | public static Plane XYZToPlane(double[] numbers) 17 | { 18 | var e = new Vector6d(numbers); 19 | e.A6 = e.A4.ToRadians(); 20 | e.A5 = e.A5.ToRadians(); 21 | e.A4 = e.A6.ToRadians(); 22 | var t = e.EulerZYXToTransform(); 23 | return t.ToPlane(); 24 | } 25 | 26 | public static double[] PlaneToXYZ(Plane plane) 27 | { 28 | var t = plane.ToTransform(); 29 | var e = t.ToEulerZYX(); 30 | return [e.A1, e.A2, e.A3, e.A6.ToDegrees(), e.A5.ToDegrees(), e.A4.ToDegrees()]; 31 | } 32 | 33 | public override double[] PlaneToNumbers(Plane plane) => PlaneToXYZ(plane); 34 | public override Plane NumbersToPlane(double[] numbers) => XYZToPlane(numbers); 35 | 36 | internal override void SaveCode(IProgram program, string folder) 37 | { 38 | if (program.Code is null) 39 | throw new InvalidOperationException(" Program code not generated"); 40 | 41 | var programDir = Path.Combine(folder, program.Name); 42 | Directory.CreateDirectory(programDir); 43 | 44 | for (int i = 0; i < program.Code.Count; i++) 45 | { 46 | //string group = MechanicalGroups[i].Name; 47 | //string programName = $"{program.Name}_{group}"; 48 | string programName = $"{program.Name}"; 49 | 50 | for (int j = 0; j < program.Code[i].Count; j++) 51 | { 52 | string name = j switch 53 | { 54 | 0 => $"{programName}.jks", 55 | _ => $"{programName}_{j - 1:000}.jks", 56 | }; 57 | 58 | string file = Path.Combine(programDir, name); 59 | var joinedCode = string.Join("\r\n", program.Code[i][j]); 60 | //File.WriteAllText(file, joinedCode); 61 | 62 | var utf8WithoutBom = new UTF8Encoding(true); 63 | var writer = new StreamWriter(file, false, utf8WithoutBom); 64 | writer.WriteLine(joinedCode); 65 | writer.Close(); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Robots/Robots.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFrameworks>netstandard2.0;net48</TargetFrameworks> 5 | <AssemblyTitle>$(Product) Core</AssemblyTitle> 6 | 7 | <PackageId>Robots</PackageId> 8 | <PackageIcon>icon128.png</PackageIcon> 9 | <Description>$(Description)</Description> 10 | 11 | </PropertyGroup> 12 | 13 | <ItemGroup> 14 | <PackageReference Include="PolySharp" Version="1.14.1" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" /> 15 | <PackageReference Include="SSH.NET" Version="2024.0.0" /> 16 | </ItemGroup> 17 | 18 | <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> 19 | <PackageReference Include="Rhino3dm" Version="7.15.0" /> 20 | <PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> 21 | </ItemGroup> 22 | 23 | <ItemGroup Condition="'$(TargetFramework)' == 'net48'"> 24 | <PackageReference Include="RhinoCommon" Version="7.0.20314.3001" ExcludeAssets="runtime" /> 25 | <Reference Include="System.Net.Http" /> 26 | <Reference Include="Newtonsoft.Json.Rhino" HintPath="..\..\lib\Newtonsoft.Json.Rhino.dll" Private="false" /> 27 | <Reference Include="ABB.Robotics.Controllers.PC" HintPath="..\..\lib\ABB.Robotics.Controllers.PC.dll" /> 28 | </ItemGroup> 29 | 30 | <ItemGroup> 31 | <EmbeddedResource Include="Resources\**\*" /> 32 | <None Include="..\..\build\Assets\icon128.png" Pack="true" PackagePath="" /> 33 | </ItemGroup> 34 | 35 | </Project> -------------------------------------------------------------------------------- /src/Robots/TargetAttributes/Frame.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public class Frame : TargetAttribute, IEquatable<Frame> 6 | { 7 | public static Frame Default { get; } = new(Plane.WorldXY, -1, -1, "DefaultFrame"); 8 | 9 | /// <summary> 10 | /// Reference frame of plane for a target 11 | /// </summary> 12 | 13 | Plane _plane; 14 | public ref Plane Plane => ref _plane; 15 | public int CoupledMechanism { get; } 16 | public int CoupledMechanicalGroup { get; } 17 | 18 | /// <summary> 19 | /// Specifies that it will use a tool that exists in the controller and does not need to be defined in the generated program. 20 | /// </summary> 21 | public bool UseController { get; } 22 | 23 | /// <summary> 24 | /// Used only in KUKA to load from the BASE_DATA array. 25 | /// </summary> 26 | public int? Number { get; } 27 | internal int CoupledPlaneIndex { get; set; } 28 | 29 | public bool IsCoupled => CoupledMechanicalGroup != -1; 30 | 31 | public Frame(Plane plane, int coupledMechanism = -1, int coupledMechanicalGroup = -1, string? name = null, bool useController = false, int? number = null) 32 | : base(name) 33 | { 34 | Plane = plane; 35 | CoupledMechanism = coupledMechanism; 36 | CoupledMechanicalGroup = coupledMechanicalGroup; 37 | UseController = number is not null || useController; 38 | Number = number; 39 | 40 | if (number is not null && number.Value < 1) 41 | throw new ArgumentOutOfRangeException(nameof(number), " Frame number out of range."); 42 | } 43 | 44 | public Frame ShallowClone() => (Frame)MemberwiseClone(); 45 | 46 | public override int GetHashCode() => Plane.GetHashCode(); 47 | public override bool Equals(object obj) => obj is Frame other && Equals(other); 48 | 49 | public bool Equals(Frame other) 50 | { 51 | return Plane == other.Plane 52 | && CoupledMechanism == other.CoupledMechanism 53 | && CoupledMechanicalGroup == other.CoupledMechanicalGroup 54 | && UseController == other.UseController 55 | && Number == other.Number 56 | && CoupledPlaneIndex == other.CoupledPlaneIndex 57 | && _name == other._name; 58 | } 59 | 60 | public override string ToString() 61 | { 62 | if (HasName) 63 | return $"Frame ({Name})"; 64 | 65 | string origin = $"{Plane.OriginX:0.##},{Plane.OriginY:0.##},{Plane.OriginZ:0.##}"; 66 | return $"Frame ({origin}" + (IsCoupled ? " Coupled" : "") + ")"; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Robots/TargetAttributes/Speed.cs: -------------------------------------------------------------------------------- 1 | using static System.Math; 2 | 3 | namespace Robots; 4 | 5 | public class Speed(double translation = 100, double rotationSpeed = PI, double translationExternal = 5000, double rotationExternal = PI * 6, string? name = null) 6 | : TargetAttribute(name), IEquatable<Speed> 7 | { 8 | public static Speed Default { get; } = new(name: "DefaultSpeed"); 9 | 10 | /// <summary> 11 | /// TCP translation speed in mm/s 12 | /// </summary> 13 | public double TranslationSpeed { get; set; } = translation; 14 | 15 | /// <summary> 16 | /// TCP rotation speed in rad/s 17 | /// </summary> 18 | public double RotationSpeed { get; set; } = rotationSpeed; 19 | 20 | /// <summary> 21 | /// Translation speed in mm/s 22 | /// </summary> 23 | public double TranslationExternal { get; set; } = translationExternal; 24 | 25 | /// <summary> 26 | /// Rotation speed in rad/s 27 | /// </summary> 28 | public double RotationExternal { get; set; } = rotationExternal; 29 | 30 | /// <summary> 31 | /// Translation acceleration in mm/s² (used in UR, Doosan) 32 | /// </summary> 33 | public double TranslationAccel { get; set; } = 1000; 34 | 35 | /// <summary> 36 | /// Axis/joint acceleration in rads/s² (used in UR, Doosan, and Franka Emika) 37 | /// </summary> 38 | public double AxisAccel { get; set; } = PI; 39 | 40 | /// <summary> 41 | /// Time in seconds it takes to reach the target. Optional parameter (used in UR and Doosan) 42 | /// </summary> 43 | public double Time { get; set; } 44 | 45 | public override int GetHashCode() => TranslationSpeed.GetHashCode(); 46 | public override bool Equals(object obj) => obj is Speed other && Equals(other); 47 | 48 | public bool Equals(Speed other) 49 | { 50 | return TranslationSpeed == other.TranslationSpeed 51 | && RotationSpeed == other.RotationSpeed 52 | && TranslationExternal == other.TranslationExternal 53 | && RotationExternal == other.RotationExternal 54 | && TranslationAccel == other.TranslationAccel 55 | && AxisAccel == other.AxisAccel 56 | && Time == other.Time 57 | && _name == other._name; 58 | } 59 | 60 | public override string ToString() => HasName 61 | ? $"Speed ({Name})" 62 | : $"Speed ({TranslationSpeed:0.#} mm/s)"; 63 | } 64 | -------------------------------------------------------------------------------- /src/Robots/TargetAttributes/TargetAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Robots; 2 | 3 | public abstract class TargetAttribute 4 | { 5 | protected string? _name; 6 | 7 | protected TargetAttribute(string? name) 8 | { 9 | if (name is not null) 10 | Name = name; 11 | } 12 | 13 | /// <summary> 14 | /// Name of the attribute 15 | /// </summary> 16 | public string Name 17 | { 18 | get => _name.NotNull(); 19 | private set 20 | { 21 | if (!Program.IsValidIdentifier(value, out var error)) 22 | throw new ArgumentException($" {GetType().Name} {error}", nameof(value)); 23 | 24 | _name = value; 25 | } 26 | } 27 | 28 | public bool HasName => _name is not null; 29 | 30 | public T CloneWithName<T>(string name) where T : TargetAttribute 31 | { 32 | var attribute = (T)MemberwiseClone(); 33 | attribute.Name = name; 34 | return attribute; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Robots/TargetAttributes/Tool.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public class Tool : TargetAttribute 6 | { 7 | public static Tool Default { get; } = new(Plane.WorldXY, "DefaultTool"); 8 | 9 | public Plane Tcp { get; } 10 | public double Weight { get; } 11 | public Point3d Centroid { get; } 12 | public Mesh Mesh { get; } 13 | 14 | /// <summary> 15 | /// Specifies that it will use a tool that exists in the controller and does not need to be defined in the generated program. 16 | /// </summary> 17 | public bool UseController { get; } 18 | 19 | /// <summary> 20 | /// Used only in KUKA to load from the TOOL_DATA array. 21 | /// </summary> 22 | public int? Number { get; } 23 | 24 | public Tool(Plane tcp, string name = "DefaultTool", double weight = 0, Point3d? centroid = null, Mesh? mesh = null, IList<Plane>? calibrationPlanes = null, bool useController = false, int? number = null) 25 | : base(name) 26 | { 27 | Weight = weight; 28 | Centroid = (centroid is null) ? tcp.Origin : (Point3d)centroid; 29 | Mesh = mesh ?? FileIO.EmptyMesh; 30 | UseController = number is not null || useController; 31 | Number = number; 32 | 33 | if (number is not null && number.Value < 1) 34 | throw new ArgumentOutOfRangeException(nameof(number), " Tool number out of range."); 35 | 36 | if (calibrationPlanes is null || !calibrationPlanes.Any()) 37 | { 38 | Tcp = tcp; 39 | } 40 | else 41 | { 42 | if (calibrationPlanes.Count != 4) 43 | throw new ArgumentException(" Calibration requires 4 planes.", nameof(calibrationPlanes)); 44 | 45 | var origin = FourPointCalibration(calibrationPlanes); 46 | Tcp = new Plane(origin, tcp.XAxis, tcp.YAxis); 47 | } 48 | } 49 | 50 | static Point3d FourPointCalibration(IList<Plane> calibrationPlanes) 51 | { 52 | var p = calibrationPlanes; 53 | var calibrate = new Geometry.CircumcentreSolver(p[0].Origin, p[1].Origin, p[2].Origin, p[3].Origin); 54 | Point3d tcpOrigin = Point3d.Origin; 55 | 56 | foreach (Plane plane in calibrationPlanes) 57 | { 58 | plane.RemapToPlaneSpace(calibrate.Center, out Point3d remappedPoint); 59 | tcpOrigin += remappedPoint; 60 | } 61 | 62 | tcpOrigin /= 4.0; 63 | return tcpOrigin; 64 | } 65 | 66 | public override string ToString() => $"Tool ({Name})"; 67 | } 68 | -------------------------------------------------------------------------------- /src/Robots/TargetAttributes/Zone.cs: -------------------------------------------------------------------------------- 1 | using static Robots.Util; 2 | 3 | namespace Robots; 4 | 5 | public class Zone(double distance, double? rotation = null, double? rotationExternal = null, string? name = null) 6 | : TargetAttribute(name), IEquatable<Zone> 7 | { 8 | public static Zone Default { get; } = new(0, name: "DefaultZone"); 9 | 10 | /// <summary> 11 | /// Radius of the TCP zone in mm 12 | /// </summary> 13 | public double Distance { get; set; } = distance; 14 | 15 | /// <summary> 16 | /// The zone size for the tool reorientation in radians. 17 | /// </summary> 18 | public double Rotation { get; set; } = rotation ?? (distance / 10).ToRadians(); 19 | 20 | /// <summary> 21 | /// The zone size for revolute external axis in radians. 22 | /// </summary> 23 | public double RotationExternal { get; set; } = rotationExternal ?? rotation ?? (distance / 10).ToRadians(); 24 | 25 | public bool IsFlyBy => Distance > DistanceTol; 26 | 27 | public override int GetHashCode() => Distance.GetHashCode(); 28 | public override bool Equals(object obj) => obj is Zone other && Equals(other); 29 | 30 | public bool Equals(Zone other) 31 | { 32 | return Distance == other.Distance 33 | && Rotation == other.Rotation 34 | && RotationExternal == other.RotationExternal 35 | && _name == other._name; 36 | } 37 | 38 | public override string ToString() => HasName 39 | ? $"Zone ({Name})" 40 | : IsFlyBy ? $"Zone ({Distance:0.##} mm)" : $"Zone (Stop point)"; 41 | } 42 | -------------------------------------------------------------------------------- /src/Robots/Targets/CartesianTarget.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | [Flags] 6 | public enum RobotConfigurations { None = 0, Shoulder = 1, Elbow = 2, Wrist = 4, Undefined = 8 } 7 | public enum Motions { Joint, Linear, Circular, Spline } 8 | 9 | public class CartesianTarget(Plane plane, RobotConfigurations? configuration = null, Motions motion = Motions.Joint, Tool? tool = null, Speed? speed = null, Zone? zone = null, Command? command = null, Frame? frame = null, IEnumerable<double>? external = null) 10 | : Target(tool, speed, zone, command, frame, external) 11 | { 12 | public Plane Plane { get; set; } = plane; 13 | public RobotConfigurations? Configuration { get; set; } = configuration; 14 | public Motions Motion { get; set; } = motion; 15 | 16 | public CartesianTarget(Plane plane, Target target, RobotConfigurations? configuration = null, Motions motion = Motions.Joint, IEnumerable<double>? external = null) 17 | : this(plane, configuration, motion, target.Tool, target.Speed, target.Zone, target.Command, target.Frame, external ?? target.External) { } 18 | 19 | public override string ToString() 20 | { 21 | string type = $"Cartesian ({Plane.OriginX:0.##},{Plane.OriginY:0.##},{Plane.OriginZ:0.##})"; 22 | string motion = $", {Motion}"; 23 | string configuration = Configuration is not null ? $", \"{Configuration}\"" : ""; 24 | string frame = $", Frame ({Frame.Plane.OriginX:0.##},{Frame.Plane.OriginY:0.##},{Frame.Plane.OriginZ:0.##})"; 25 | string tool = $", {Tool}"; 26 | string speed = $", {Speed}"; 27 | string zone = $", {Zone}"; 28 | string commands = Command != Command.Default ? ", Contains commands" : ""; 29 | string external = External.Length > 0 ? $", {External.Length:0} external axes" : ""; 30 | return $"Target ({type}{motion}{configuration}{frame}{tool}{speed}{zone}{commands}{external})"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Robots/Targets/Target.cs: -------------------------------------------------------------------------------- 1 | using static Robots.Util; 2 | 3 | namespace Robots; 4 | 5 | public abstract class Target(Tool? tool, Speed? speed, Zone? zone, Command? command, Frame? frame, IEnumerable<double>? external) : IToolpath 6 | { 7 | public static Target Default { get; } = new JointTarget([0, HalfPI, 0, 0, 0, 0]); 8 | 9 | public Tool Tool { get; set; } = tool ?? Tool.Default; 10 | public Frame Frame { get; set; } = frame ?? Frame.Default; 11 | public Speed Speed { get; set; } = speed ?? Speed.Default; 12 | public Zone Zone { get; set; } = zone ?? Zone.Default; 13 | public Command Command { get; set; } = command ?? Command.Default; 14 | public double[] External { get; set; } = (external is not null) ? external.ToArray() : []; 15 | public string[]? ExternalCustom { get; set; } 16 | 17 | public IEnumerable<Target> Targets => Enumerable.Repeat(this, 1); 18 | 19 | public void AppendCommand(Command command) 20 | { 21 | var current = Command; 22 | 23 | if (current is null || current == Command.Default) 24 | { 25 | Command = command; 26 | } 27 | else 28 | { 29 | var group = new Commands.Group(); 30 | 31 | if (current is Commands.Group currentGroup) 32 | group.AddRange(currentGroup); 33 | else 34 | group.Add(current); 35 | 36 | group.Add(command); 37 | Command = group; 38 | } 39 | } 40 | 41 | public Target ShallowClone() => (Target)MemberwiseClone(); 42 | IToolpath IToolpath.ShallowClone(List<Target>? targets) => (IToolpath)MemberwiseClone(); 43 | } 44 | -------------------------------------------------------------------------------- /src/Robots/Targets/Toolpath.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace Robots; 4 | 5 | public interface IToolpath 6 | { 7 | IEnumerable<Target> Targets { get; } 8 | IToolpath ShallowClone(List<Target>? targets = null); 9 | } 10 | 11 | public class SimpleToolpath : IToolpath, IEnumerable<Target> 12 | { 13 | protected List<Target> _targets = []; 14 | public IEnumerable<Target> Targets => _targets; 15 | 16 | public SimpleToolpath() { } 17 | 18 | public SimpleToolpath(IEnumerable<IToolpath> toolpaths) 19 | { 20 | _targets = [.. toolpaths.SelectMany(t => t.Targets)]; 21 | } 22 | 23 | public void Add(Target target) 24 | { 25 | _targets.Add(target); 26 | } 27 | 28 | public IEnumerator<Target> GetEnumerator() => _targets.GetEnumerator(); 29 | IEnumerator IEnumerable.GetEnumerator() => _targets.GetEnumerator(); 30 | 31 | public IToolpath ShallowClone(List<Target>? targets = null) 32 | { 33 | targets ??= [.. _targets]; 34 | 35 | var clone = (SimpleToolpath)MemberwiseClone(); 36 | clone._targets = targets; 37 | return clone; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Robots/Visualization/MeshPoser.cs: -------------------------------------------------------------------------------- 1 | namespace Robots; 2 | 3 | public interface IMeshPoser 4 | { 5 | void Pose(List<KinematicSolution> solutions, Tool[] tools); 6 | } 7 | 8 | public static class IMeshPoserExtensions 9 | { 10 | public static void Pose(this IMeshPoser poser, List<KinematicSolution> solutions, SystemTarget systemTarget) 11 | { 12 | var tools = systemTarget.ProgramTargets.Map(t => t.Target.Tool); 13 | poser.Pose(solutions, tools); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Robots/Visualization/RhinoMeshPoser.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public class RhinoMeshPoser : IMeshPoser 6 | { 7 | public static List<Mesh> Pose(RobotSystem robot, List<KinematicSolution> solutions, IList<Target> targets) 8 | { 9 | var tools = targets.Map(t => t.Tool); 10 | var poser = new RhinoMeshPoser(robot); 11 | poser.Pose(solutions, tools); 12 | return poser.Meshes; 13 | } 14 | 15 | // Instance 16 | 17 | public List<Mesh> Meshes { get; } 18 | 19 | readonly DefaultPose _default; 20 | 21 | public RhinoMeshPoser(RobotSystem robot) 22 | { 23 | _default = robot.DefaultPose; 24 | 25 | var meshCount = _default.Meshes.Sum(m => m.Count + 1); 26 | Meshes = new List<Mesh>(meshCount); 27 | } 28 | 29 | public void Pose(List<KinematicSolution> solutions, Tool[] tools) 30 | { 31 | Meshes.Clear(); 32 | 33 | for (int i = 0; i < solutions.Count; i++) 34 | { 35 | AddGroupPose(Meshes, solutions[i].Planes, tools[i].Mesh, _default.Planes[i], _default.Meshes[i]); 36 | } 37 | } 38 | 39 | static void AddGroupPose(List<Mesh> meshes, Plane[] planes, Mesh tool, List<Plane> defaultPlanes, List<Mesh> defaultMeshes) 40 | { 41 | for (int i = 0; i < planes.Length - 1; i++) 42 | { 43 | var t = Transform.PlaneToPlane(defaultPlanes[i], planes[i]); 44 | var mesh = defaultMeshes[i].DuplicateMesh(); 45 | mesh.Transform(t); 46 | meshes.Add(mesh); 47 | } 48 | 49 | var toolMesh = tool.DuplicateMesh(); 50 | toolMesh.Transform(planes[^2].ToTransform()); 51 | meshes.Add(toolMesh); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Robots/Visualization/SimpleTrail.cs: -------------------------------------------------------------------------------- 1 | using Rhino.Geometry; 2 | 3 | namespace Robots; 4 | 5 | public class SimpleTrail(Program program, double maxLength, int mechanicalGroup = 0) 6 | { 7 | readonly Program _program = program; 8 | readonly int _mechanicalGroup = mechanicalGroup; 9 | double _time = program.CurrentSimulationPose.CurrentTime; 10 | 11 | public double Length { get; set; } = maxLength; 12 | public Polyline Polyline { get; } = []; 13 | 14 | public void Update() 15 | { 16 | var currentTime = _program.CurrentSimulationPose.CurrentTime; 17 | if (currentTime < _time) 18 | Polyline.Clear(); 19 | 20 | _time = currentTime; 21 | Polyline.Add(_program.CurrentSimulationPose.GetLastPlane(_mechanicalGroup).Origin); 22 | 23 | while (Polyline.Length > Length) 24 | Polyline.RemoveAt(0); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Robots.Tests/Program.cs: -------------------------------------------------------------------------------- 1 |  2 | //dotnet run --property:Configuration=Release 3 | // new Performance(); 4 | -------------------------------------------------------------------------------- /tests/Robots.Tests/Robots.Tests.csproj: -------------------------------------------------------------------------------- 1 | <Project Sdk="Microsoft.NET.Sdk"> 2 | 3 | <PropertyGroup> 4 | <TargetFramework>net8.0</TargetFramework> 5 | <IsPackable>false</IsPackable> 6 | <GenerateProgramFile>true</GenerateProgramFile> 7 | </PropertyGroup> 8 | 9 | <ItemGroup> 10 | <PackageReference Include="NUnit" Version="4.1.0" /> 11 | <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" /> 12 | <PackageReference Include="NUnit3TestAdapter" Version="4.5.0" /> 13 | </ItemGroup> 14 | 15 | <ItemGroup> 16 | <ProjectReference Include="..\..\src\Robots\Robots.csproj" /> 17 | </ItemGroup> 18 | 19 | </Project> 20 | --------------------------------------------------------------------------------