cscの作法 その581

# 概要
cscの作法、調べてみた。
OpenRCF v2.8、見つけたので、windows11で、MSbuildしてみた。
シュミレーションやってみた。

# 参考にしたページ

https://qiita.com/sekky0816/items/b11d6fa16c6df9034eb6

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8fd2dab8-b7d1-43ef-aaa9-ec992a5505e9.png)

# サンプルコード

```

using System;
using System.Windows;
using OpenRCF;
using Vector = OpenRCF.Vector;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;


namespace OpenRCF
{
	class InvertedPendulum {
		private readonly static float g = 9.80665f;
		private Cuboid Pole = new Cuboid(0.1f, 0.1f, 0.8f);
		private Pillar Joint = new Pillar();
		private Cuboid Base = new Cuboid(0.4f, 0.4f, 0.2f);
		private float poleLength = 0.5f;
		private float poleMass = 0.2f;
		private float baseMass = 0.2f;
		private bool isDynamicsEnabled = false;
		private void CalcDynamics() {
			float CosTh = (float) Math.Cos(Theta);
			float SinTh = (float) Math.Sin(Theta);
			float force = Force - PoleMass * g * CosTh * SinTh;
			Velocity += SamplingTime * force / (BaseMass + PoleMass);
			Position += SamplingTime * Velocity;
			Joint.Position[0] = Position;
			float poleForce = PoleMass / (BaseMass + PoleMass) * force;
			Torque = 0.5f * poleLength * (PoleMass * g * SinTh - poleForce * CosTh);
			Omega += SamplingTime * Torque / Inertia;
			Theta += SamplingTime * Omega;
			if (Theta > 1.6)
				return;
			if (Theta < -1.6)
				return;
			Joint.Rotate.SetRy(Theta);
		}
		public float Inertia {
			get;
			private set;
		}
		public float Position,
			Velocity;
		public float Theta,
			Omega,
			Torque;
		public float Force;
		public float samplingTime = 0.05f;
		public float SamplingTime {
			get {
				return samplingTime;
			}
			set {
				if (isDynamicsEnabled)
				{
					Console.WriteLine("Error: SamplingTime setting must be before StartDynamics().");
				}
				else if (value < 0.001f)
				{
					Console.WriteLine("Error: SamplingTime is too small.");
				}
				else
				{
					samplingTime = value;
				}
			}
		}
		public float PoleLength {
			get {
				return poleLength;
			}
			set {
				poleLength = value;
				Inertia = 0.25f * poleMass * poleLength * poleLength;
				Pole.SetSize(0.1f * poleLength, 0.1f * poleLength, poleLength);
				Pole.SetPositionOffset(0, 0, 0.5f * Pole.SizeZ);
				Joint.Radius = 0.075f * poleLength;
				Joint.Height = 0.12f * poleLength;
			}
		}
		public float PoleMass {
			get {
				return poleMass;
			}
			set {
				if (0 < value)
				{
					poleMass = value;
					Inertia = 0.25f * poleMass * poleLength * poleLength;
				}
				else
				{
					Console.WriteLine("Error: Mass must be greater than 0.");
				}
			}
		}
		public float BaseMass {
			get {
				return baseMass;
			}
			set {
				if (0 < value)
					baseMass = value;
				else
					Console.WriteLine("Error: Mass must be greater than 0.");
			}
		}
		public InvertedPendulum(float poleLength = 0.8f) {
			PoleLength = poleLength;
			Pole.Position = Joint.Position;
			Pole.Rotate = Joint.Rotate;
			Base.Position = Joint.Position;
			Base.SetPositionOffset(0, 0, -0.5f * Base.SizeZ);
			Joint.SetRotateOffset(0.5f * (float) Math.PI, 0, 0);
			Joint.Color.SetLightGray();
			Joint.Position[2] = Base.SizeZ;
		}
		public void SetBaseSize(float sizeX, float sizeY, float sizeZ) {
			Base.SetSize(sizeX, sizeY, sizeZ);
			Base.SetPositionOffset(0, 0, -0.5f * Base.SizeZ);
			Joint.Position[2] = Base.SizeZ;
		}
		public void Draw() {
			Pole.Draw();
			Joint.Draw();
			Base.Draw();
		}
		public void StartDynamics() {
			if (isDynamicsEnabled == false)
			{
				Parallel.RunEndless(CalcDynamics, (uint) (1000 * SamplingTime));
				isDynamicsEnabled = true;
			}
			else
			{
				Console.WriteLine("Warning: Dynamics is already enabled.");
			}
		}
		public void Reset() {
			Force = 0;
			Position = 0;
			Velocity = 0;
			Theta = 0;
			Omega = 0;
		}
	}


    
	partial class MainWindow: Window {
		InvertedPendulum InvertedPendulum = new InvertedPendulum();
		void P_Control() {
			float Kp = 12;
			InvertedPendulum.Force = Kp * InvertedPendulum.Theta;
		}
		void Setup() {
			InvertedPendulum.PoleLength = 0.8f;
			InvertedPendulum.PoleMass = 0.2f;
			InvertedPendulum.BaseMass = 0.2f;
			Button1.Content = "start";
			Button2.Content = "push";
			Button3.Content = "p_con";
			Button4.Content = "reset";
			Button5.Content = "none";
		}
		void Loop() {
			//Console.WriteLine(InvertedPendulum.Theta);
		}
		void Draw() {
			InvertedPendulum.Draw();
		}
		void Button1_Click(object sender, RoutedEventArgs e) {
			InvertedPendulum.StartDynamics();
		}
		void Button2_Click(object sender, RoutedEventArgs e) {
			InvertedPendulum.Theta += 0.01f;
		}
		void Button3_Click(object sender, RoutedEventArgs e) {
			Parallel.RunEndless(P_Control, 50);
		}
		void Button4_Click(object sender, RoutedEventArgs e) {
			InvertedPendulum.Reset();
		}
		void Button5_Click(object sender, RoutedEventArgs e) {
			InvertedPendulum.Force = 0.01f;
		}
	}
}




```

以上。