AnalysisDialog.cpp
#include "StdAfx.h"
#include "AnalysisDialog.h"
#include "Motion.h"
#include "Pose.h"
#include "Model.h"
#include "Link.h"
#include "Torque.h"
#include "ListViewItemComparer.h"
using namespace Core;
using namespace Robotics;
using namespace System;
using namespace System::Diagnostics;
/// [ Constructor ]
AnalysisDialog::AnalysisDialog( void )
{
// コンポーネントを初期化する
InitializeComponent();
}
/// [ Destructor ]
AnalysisDialog::~AnalysisDialog()
{
if( components != nullptr )
{
delete components;
}
}
#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
void AnalysisDialog::InitializeComponent(void)
{
this->m_listView = (gcnew System::Windows::Forms::ListView());
this->m_nameHeader = (gcnew System::Windows::Forms::ColumnHeader());
this->m_maximumTorqueHeader = (gcnew System::Windows::Forms::ColumnHeader());
this->m_operationalAngleHeader = (gcnew System::Windows::Forms::ColumnHeader());
this->m_maximumAngularVelocityHeader = (gcnew System::Windows::Forms::ColumnHeader());
this->SuspendLayout();
//
// m_listView
//
this->m_listView->Columns->AddRange(gcnew cli::array< System::Windows::Forms::ColumnHeader^ >(4) {this->m_nameHeader, this->m_operationalAngleHeader,
this->m_maximumAngularVelocityHeader, this->m_maximumTorqueHeader});
this->m_listView->Dock = System::Windows::Forms::DockStyle::Fill;
this->m_listView->Location = System::Drawing::Point(0, 0);
this->m_listView->MultiSelect = false;
this->m_listView->Name = L"m_listView";
this->m_listView->Size = System::Drawing::Size(492, 472);
this->m_listView->TabIndex = 1;
this->m_listView->UseCompatibleStateImageBehavior = false;
this->m_listView->View = System::Windows::Forms::View::Details;
this->m_listView->ColumnClick += gcnew System::Windows::Forms::ColumnClickEventHandler(this, &AnalysisDialog::ListViewColumnClick);
//
// m_nameHeader
//
this->m_nameHeader->Text = L"名称";
this->m_nameHeader->Width = 80;
//
// m_maximumTorqueHeader
//
this->m_maximumTorqueHeader->Text = L"最大トルク [Nm]";
this->m_maximumTorqueHeader->TextAlign = System::Windows::Forms::HorizontalAlignment::Right;
this->m_maximumTorqueHeader->Width = 120;
//
// m_operationalAngleHeader
//
this->m_operationalAngleHeader->Text = L"動作角度 [deg]";
this->m_operationalAngleHeader->TextAlign = System::Windows::Forms::HorizontalAlignment::Right;
this->m_operationalAngleHeader->Width = 120;
//
// m_maximumAngularVelocityHeader
//
this->m_maximumAngularVelocityHeader->Text = L"最大角速度 [deg/sec]";
this->m_maximumAngularVelocityHeader->TextAlign = System::Windows::Forms::HorizontalAlignment::Right;
this->m_maximumAngularVelocityHeader->Width = 140;
//
// AnalysisDialog
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(492, 472);
this->Controls->Add(this->m_listView);
this->MaximizeBox = false;
this->MinimizeBox = false;
this->Name = L"AnalysisDialog";
this->ShowIcon = false;
this->ShowInTaskbar = false;
this->Text = L"分析";
this->ResumeLayout(false);
}
#pragma endregion
/// 表示する
void AnalysisDialog::Show( Motion^ motion, Model^ model )
{
Debug::Assert( model != nullptr, "モデルは生成されている" );
// モデルから リンクを取得する
Links^ links = model->Links;
// ... 動作角度を取得する
array< Robotics::AngleRange >^ operationalAngle = GetOperationalAngle( motion, links->Length );
// ... 角速度の最大値を取得する
array< double >^ maximumAngularVelocity = GetMaximumAngularVelocity( motion, links->Length );
// トルクの最大値を取得する
array< double >^ maximumTorque = GetMaximumTorque( motion, model );
// 全てのリンクの リストの項目を生成する
for( int i = 1; i < links->Length; i++ )
{
// リンクの名称を与えて リストの項目を生成する
Windows::Forms::ListViewItem^ item = gcnew Windows::Forms::ListViewItem( links[ i ]->Name );
Windows::Forms::ListViewItem::ListViewSubItemCollection^ subItem = item->SubItems; // サブ項目
// ... 動作角度を Degreeに変換して追加する
subItem->Add( Angle::CalculateDegree( operationalAngle[ i ].Size ).ToString( "0.0" ) );
// ... 角速度の最大値を Degreeに変換して追加する
subItem->Add( Angle::CalculateDegree( maximumAngularVelocity[ i ] ).ToString( "0.0" ) );
// ... トルクの最大値を追加する
subItem->Add( maximumTorque[ i ].ToString( "0.000" ) );
// 項目をリストビューに追加する
m_listView->Items->Add( item );
}
// リストビュー アイテムの比較クラスを生成する
m_listViewItemComparer = gcnew ListViewItemComparer();
// ... それをリストビューの並べ替えの方法として指定する
m_listView->ListViewItemSorter = m_listViewItemComparer;
// フォームを表示する
this->ShowDialog();
}
/// リストビューの列がクリックされた
System::Void AnalysisDialog::ListViewColumnClick( System::Object^, System::Windows::Forms::ColumnClickEventArgs^ e )
{
// クリックされた列を 並べ替えの対象として設定する
m_listViewItemComparer->Column = e->Column;
// ... リストビューを並べ替える
m_listView->Sort();
}
/// 動作角度を取得する
array< Robotics::AngleRange >^ AnalysisDialog::GetOperationalAngle( Motion^ motion, int linkSum )
{
// 角度の範囲を格納する配列を リンク数だけ生成する
array< Robotics::AngleRange >^ result = gcnew array< AngleRange >( linkSum );
for( int i = 0; i < linkSum; i++ )
{
// 範囲を 下限を最も大きな値、上限を最も小さな値で初期化する
result[ i ] = AngleRange( Double::MaxValue, Double::MinValue );
}
// 全てのポーズの 速度を取得する
for( int k = 0; k < motion->PoseCount; k++ )
{
Angles^ angles = motion[ k ]->AngleOfJoints; // 各関節の角度
// 胴体以外の全てのリンクについて、現在の値と比較する
for( int i = 1; i < linkSum; i++ )
{
result[ i ].ExpandRange( angles[ i ] );
}
}
return result;
}
/// 角速度の最大値を取得する
array< double >^ AnalysisDialog::GetMaximumAngularVelocity( Motion^ motion, int linkSum )
{
// トルクの最大値を格納する配列を リンク数だけ生成する
array< double >^ result = gcnew array< double >( linkSum );
// 全てのポーズの 角速度を取得する
for( int k = 0; k < motion->PoseCount; k++ )
{
AngularVelocities^ angularVelocities = motion->GetAngularVelocities( k ); // 各関節の角速度
// 胴体以外の全てのリンクについて、現在の値と比較する
for( int i = 1; i < linkSum; i++ )
{
if( result[ i ] < angularVelocities[ i ] )
{
// 現在の値を越えるならば、その値に更新する
result[ i ] = angularVelocities[ i ];
}
}
}
return result;
}
/// トルクの最大値を取得する
array< double >^ AnalysisDialog::GetMaximumTorque( Motion^ motion, Model^ model )
{
// モデルから リンクを取得する
Links^ links = model->Links;
// ... トルクの最大値を格納する配列を リンク数だけ生成する
array< double >^ result = gcnew array< double >( links->Length );
// モデルに モーション中の全てのポーズをとらせる
for( int k = 0; k < motion->PoseCount; k++ )
{
// モデルにポーズをとらせる
motion[ k ]->PosedModel( model );
// ... その状態におけるモデルの トルクを生成する
Torque^ torque = gcnew Torque( model );
// 胴体以外の 全てのリンクについて、現在の値と比較する
for( int i = 1; i < links->Length; i++ )
{
// リンクの トルクの絶対値
double linkTorque = Math::Abs( torque[ links[ i ] ] );
if( result[ i ] < linkTorque )
{
// 現在の値を越えるならば、その値に更新する
result[ i ] = linkTorque;
}
}
}
// モデルに 現在のポーズをとらせる
motion->CurrentPose->PosedModel( model );
return result;
}