Initial tutorial project
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
using CartActivator;
|
||||
using CommonUsage.Chassis;
|
||||
using System.Numerics;
|
||||
|
||||
namespace MultiWheelM;
|
||||
|
||||
[UseManualController(manualController = typeof(Remote))]
|
||||
[UseLadderLogic(logic = typeof(MotorRoutine), scanInterval = 50)]
|
||||
public class CartDefinition : CartActivator.CartDefinition
|
||||
{
|
||||
[AsUpperIO(desc = "左前轮速度", timeOutReset = true)]
|
||||
[Playground]
|
||||
public float SpeedLeftFront;
|
||||
|
||||
[AsUpperIO(desc = "左后轮速度", timeOutReset = true)]
|
||||
[Playground]
|
||||
public float SpeedLeftRear;
|
||||
|
||||
[AsUpperIO(desc = "右前轮速度", timeOutReset = true)]
|
||||
[Playground]
|
||||
public float SpeedRightFront;
|
||||
|
||||
[AsUpperIO(desc = "右后轮速度", timeOutReset = true)]
|
||||
[Playground]
|
||||
public float SpeedRightRear;
|
||||
|
||||
[AsLowerIO(desc = "左前轮速度反馈")]
|
||||
[Playground]
|
||||
public float ActualSpeedLeftFront;
|
||||
|
||||
[AsLowerIO(desc = "左后轮速度反馈")]
|
||||
[Playground]
|
||||
public float ActualSpeedLeftRear;
|
||||
|
||||
[AsLowerIO(desc = "右前轮速度反馈")]
|
||||
[Playground]
|
||||
public float ActualSpeedRightFront;
|
||||
|
||||
[AsLowerIO(desc = "右后轮速度反馈")]
|
||||
[Playground]
|
||||
public float ActualSpeedRightRear;
|
||||
|
||||
[AsUpperIO(desc = "左前轮转向角度", timeOutReset = true)]
|
||||
[Playground]
|
||||
public float ThLeftFront;
|
||||
|
||||
[AsUpperIO(desc = "左后轮转向角度", timeOutReset = true)]
|
||||
[Playground]
|
||||
public float ThLeftRear;
|
||||
|
||||
[AsUpperIO(desc = "右前轮转向角度", timeOutReset = true)]
|
||||
[Playground]
|
||||
public float ThRightFront;
|
||||
|
||||
[AsUpperIO(desc = "右后轮转向角度", timeOutReset = true)]
|
||||
[Playground]
|
||||
public float ThRightRear;
|
||||
|
||||
[AsLowerIO(desc = "左前轮转向角度反馈")]
|
||||
[Playground]
|
||||
public float ActualThLeftFront;
|
||||
|
||||
[AsLowerIO(desc = "左后轮转向角度反馈")]
|
||||
[Playground]
|
||||
public float ActualThLeftRear;
|
||||
|
||||
[AsLowerIO(desc = "右前轮转向角度反馈")]
|
||||
[Playground]
|
||||
public float ActualThRightFront;
|
||||
|
||||
[AsLowerIO(desc = "右后轮转向角度反馈")]
|
||||
[Playground]
|
||||
public float ActualThRightRear;
|
||||
|
||||
[AsLowerIO(desc = "遥控模式")]
|
||||
public int ManualMode = -1;
|
||||
|
||||
[AsInitParam(desc = "手动最大速度(m/s)")]
|
||||
public float MaxManualSpeed = 0.3f;
|
||||
|
||||
[AsInitParam(desc = "手动最大自旋角速度(deg/s)")]
|
||||
public float MaxManualAngularSpeed = 45f;
|
||||
|
||||
[AsInitParam(desc = "手动最大转向角度(deg)")]
|
||||
public float MaxManualTheta = 45f;
|
||||
|
||||
[AsInitParam(desc = "遥控转向输入幂数")]
|
||||
public float ManualThetaPow = 2f;
|
||||
|
||||
[AsInitParam(desc = "舵轮前后半轴距(mm)")]
|
||||
public float WheelBaseHalfLength = 750f;
|
||||
|
||||
[AsInitParam(desc = "舵轮左右半轮距(mm)")]
|
||||
public float WheelTrackHalfWidth = 500f;
|
||||
|
||||
[AsInitParam(desc = "舵轮最小角度(deg)")]
|
||||
public float WheelAngleLowerLimit = -120f;
|
||||
|
||||
[AsInitParam(desc = "舵轮最大角度(deg)")]
|
||||
public float WheelAngleUpperLimit = 120f;
|
||||
|
||||
[AsInitParam(desc = "底盘速度加速度(m/s^2)")]
|
||||
public float ChassisAccPerSecond = 0.3f;
|
||||
|
||||
[AsInitParam(desc = "底盘速度减速度(m/s^2)")]
|
||||
public float ChassisDeAccPerSecond = 0.5f;
|
||||
|
||||
[AsInitParam(desc = "转向最低速度系数")]
|
||||
public float ChassisMinTurnSpeedFac = 0.25f;
|
||||
|
||||
[AsInitParam(desc = "几何控制点半径(mm)")]
|
||||
public float ChassisControlPointRadius = 500f;
|
||||
|
||||
[AsInitParam(desc = "几何控制点转角速度(deg/s)")]
|
||||
public float ChassisGcpThetaPerSecond = 10f;
|
||||
|
||||
[AsInitParam(desc = "阿克曼最小转向角(deg)")]
|
||||
public float ChassisMinimumTurningAngleForAckermann = 60f;
|
||||
|
||||
public MultiWheelChassis Chassis = null!;
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
Chassis = new MultiWheelChassis
|
||||
{
|
||||
MaxSpeed = MaxManualSpeed,
|
||||
AccPerSecond = ChassisAccPerSecond,
|
||||
DeAccPerSecond = ChassisDeAccPerSecond,
|
||||
MinTurnSpeedFac = ChassisMinTurnSpeedFac,
|
||||
ControlPointRadius = ChassisControlPointRadius,
|
||||
GcpThetaPerSecond = ChassisGcpThetaPerSecond,
|
||||
MinimumTurningAngleForAckermann = ChassisMinimumTurningAngleForAckermann
|
||||
};
|
||||
|
||||
Chassis.AddWheel(new SteerWheel(
|
||||
new Vector2(WheelBaseHalfLength, WheelTrackHalfWidth),
|
||||
WheelAngleLowerLimit,
|
||||
WheelAngleUpperLimit,
|
||||
speed => SpeedLeftFront = speed,
|
||||
() => ActualSpeedLeftFront,
|
||||
angle => ThLeftFront = angle,
|
||||
() => ActualThLeftFront));
|
||||
|
||||
Chassis.AddWheel(new SteerWheel(
|
||||
new Vector2(-WheelBaseHalfLength, WheelTrackHalfWidth),
|
||||
WheelAngleLowerLimit,
|
||||
WheelAngleUpperLimit,
|
||||
speed => SpeedLeftRear = speed,
|
||||
() => ActualSpeedLeftRear,
|
||||
angle => ThLeftRear = angle,
|
||||
() => ActualThLeftRear));
|
||||
|
||||
Chassis.AddWheel(new SteerWheel(
|
||||
new Vector2(WheelBaseHalfLength, -WheelTrackHalfWidth),
|
||||
WheelAngleLowerLimit,
|
||||
WheelAngleUpperLimit,
|
||||
speed => SpeedRightFront = speed,
|
||||
() => ActualSpeedRightFront,
|
||||
angle => ThRightFront = angle,
|
||||
() => ActualThRightFront));
|
||||
|
||||
Chassis.AddWheel(new SteerWheel(
|
||||
new Vector2(-WheelBaseHalfLength, -WheelTrackHalfWidth),
|
||||
WheelAngleLowerLimit,
|
||||
WheelAngleUpperLimit,
|
||||
speed => SpeedRightRear = speed,
|
||||
() => ActualSpeedRightRear,
|
||||
angle => ThRightRear = angle,
|
||||
() => ActualThRightRear));
|
||||
|
||||
Chassis.Initialize();
|
||||
|
||||
Console.WriteLine("[MultiWheelM] Minimal multi-wheel Medulla cart initialized with CommonUsage chassis geometry.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using CartActivator;
|
||||
|
||||
namespace MultiWheelM;
|
||||
|
||||
public class MotorRoutine : LadderLogic<CartDefinition>
|
||||
{
|
||||
public override void Operation(int iteration)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<OutputPath>..\build\Medulla\plugins\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="CartActivator">
|
||||
<HintPath>D:\MDCS\Release\Medulla\RefCartActivator.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="MedullaCore">
|
||||
<HintPath>D:\MDCS\Release\Medulla\RefMedullaCore.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Medulla">
|
||||
<HintPath>D:\MDCS\Release\Medulla\RefMedulla2.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="FundamentalLib">
|
||||
<HintPath>D:\MDCS\Dependencies\deps\RefFundamentalLib.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="CommonUsage">
|
||||
<HintPath>D:\MDCS\Dependencies\Commons\CommonUsage.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,70 @@
|
||||
using CartActivator;
|
||||
|
||||
namespace MultiWheelM;
|
||||
|
||||
public class Remote : ManualController<CartDefinition>
|
||||
{
|
||||
[AsControlItem(name = "速度摇杆", keyboard = "Up,Down,Left,Right", joystick = "Axis0,Axis1")]
|
||||
public Stick SpeedPad;
|
||||
|
||||
[AsControlItem(name = "速度比例", keyboard = "Q,W")]
|
||||
public Throttle SpeedRatio;
|
||||
|
||||
[AsControlItem(name = "旋转模式", keyboard = "R")]
|
||||
public Switch SpinMode;
|
||||
|
||||
[AsControlItem(name = "横移模式", keyboard = "C")]
|
||||
public Switch CrabMode;
|
||||
|
||||
[AsControlItem(name = "斜行模式", keyboard = "S")]
|
||||
public Switch SwayMode;
|
||||
|
||||
[AsControlItem(name = "车头方向", keyboard = "A,D")]
|
||||
public DThrottle FrontDirection;
|
||||
|
||||
public override void Operation()
|
||||
{
|
||||
var speedThreshold = Math.Clamp(SpeedRatio.val, 0, 1) * Math.Max(0, cart.MaxManualSpeed);
|
||||
var speed = Math.Clamp(SpeedPad.y, -1, 1) * speedThreshold;
|
||||
var steerInput = Math.Clamp(SpeedPad.x, -1, 1);
|
||||
var steering = (float)Math.Pow(Math.Abs(steerInput), cart.ManualThetaPow) * Math.Sign(steerInput);
|
||||
var frontTh = -steering * cart.MaxManualTheta;
|
||||
var rearTh = steering * cart.MaxManualTheta;
|
||||
var frontDirection = Math.Clamp(FrontDirection.dval, -1, 1) * 180;
|
||||
|
||||
if (SpinMode.on)
|
||||
{
|
||||
var direction = steerInput == 0 ? Math.Sign(speed) : steerInput;
|
||||
cart.Chassis.SendRotateMotion(direction * cart.MaxManualAngularSpeed * Math.Clamp(SpeedRatio.val, 0, 1));
|
||||
cart.ManualMode = 1;
|
||||
statusText = $"spin, w={direction * cart.MaxManualAngularSpeed:0.0}deg/s";
|
||||
return;
|
||||
}
|
||||
|
||||
if (CrabMode.on)
|
||||
{
|
||||
cart.Chassis.SetOriginBias(0, 0, 90);
|
||||
cart.Chassis.SendMotion(speed, frontTh, rearTh);
|
||||
cart.ManualMode = 2;
|
||||
statusText = $"crab, v={speed:0.000}, front={frontTh:0.0}, rear={rearTh:0.0}";
|
||||
return;
|
||||
}
|
||||
|
||||
if (SwayMode.on)
|
||||
{
|
||||
cart.Chassis.SetOriginBias(0, 0, frontDirection);
|
||||
cart.Chassis.SendMotion(speed, frontTh, -rearTh);
|
||||
cart.ManualMode = 3;
|
||||
statusText = $"sway, v={speed:0.000}, front={frontTh:0.0}, rear={-rearTh:0.0}";
|
||||
return;
|
||||
}
|
||||
|
||||
cart.Chassis.SetOriginBias(0, 0, frontDirection);
|
||||
cart.Chassis.SendMotion(speed, frontTh, rearTh);
|
||||
cart.ManualMode = 0;
|
||||
statusText = $"normal, v={speed:0.000}, front={frontTh:0.0}, rear={rearTh:0.0}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user