Skip to content

Instantly share code, notes, and snippets.

@carlosjoserg
Last active October 3, 2018 10:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlosjoserg/0e0753bb09f10d55315a88a7dbea2c33 to your computer and use it in GitHub Desktop.
Save carlosjoserg/0e0753bb09f10d55315a88a7dbea2c33 to your computer and use it in GitHub Desktop.
Read joint values in CSV format and plot it within AdskF360. CSV file needs to be placed next to the F360 binary files
// Generic CXX
#include <thread>
#include <chrono>
#include <iostream>
#include <map>
#include <algorithm>
#include <vector>
#include <iterator>
#include <fstream>
#include <sstream>
#include <string>
// F360 API
#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>
#include <CAM/CAMAll.h>
#include <Fusion/Components/RevoluteJointMotion.h>
#include <Fusion/Components/CylindricalJointMotion.h>
#include <Fusion/Components/Component.h>
using namespace adsk::core;
using namespace adsk::fusion;
using namespace adsk::cam;
///////////////
// CSV CLASS //
///////////////
class CSVRow
{
public:
std::string const& operator[](std::size_t __index) const
{
return m_data__[__index];
}
std::size_t size() const
{
return m_data__.size();
}
void readNextRow(std::istream& __str)
{
std::string line;
std::getline(__str, line);
std::stringstream lineStream(line);
std::string cell;
m_data__.clear();
// CHOOSE YOUR DELIMITER HERE
while (std::getline(lineStream, cell, ','))
{
m_data__.push_back(cell);
}
// This checks for a trailing comma with no data after it.
if (!lineStream && cell.empty())
{
// If there was a trailing comma then add an empty element.
m_data__.push_back("");
}
}
private:
std::vector<std::string> m_data__;
};
std::istream& operator>>(std::istream& str, CSVRow& data)
{
data.readNextRow(str);
return str;
}
///////////////////
// END CSV CLASS //
///////////////////
Ptr<Application> app;
Ptr<UserInterface> ui;
extern "C" XI_EXPORT bool run(const char* context)
{
// F360 stuff
app = Application::get();
if (!app)
return false;
ui = app->userInterface();
if (!ui)
return false;
Ptr<Product> product = app->activeProduct();
if (!product)
return false;
Ptr<Design> design = product;
if (!design)
return false;
// Get the root component of the active design
Ptr<Component> rootComp = design->rootComponent();
if (!rootComp)
return false;
Ptr<Joints> joints = rootComp->joints();
if (!joints)
return false;
/*
* DESIGN DEPENDANT CODE
*
* Name joints, and get them here by type
*/
// Get Revolute joints by Id
Ptr<RevoluteJointMotion> theta1 = joints->itemByName("theta1")->jointMotion();
if (!theta1)
return false;
Ptr<RevoluteJointMotion> theta3 = joints->itemByName("theta3")->jointMotion();
if (!theta3)
return false;
Ptr<RevoluteJointMotion> theta5 = joints->itemByName("theta5")->jointMotion();
if (!theta5)
return false;
// Get Cylindrical joints by Id
Ptr<CylindricalJointMotion> theta2 = joints->itemByName("theta2")->jointMotion();
if (!theta2)
return false;
Ptr<CylindricalJointMotion> theta4 = joints->itemByName("theta4")->jointMotion();
if (!theta4)
return false;
/* CSV File config
*
* I don't know how to pass absolute paths in windows!
* Solution: you need to find where the F360 binaries (the one executing the program) are
* and paste your file there
*
* Here is where you customize the filename
*/
std::string filename("solutions.txt");
std::ifstream file(filename.c_str());
std::string textFile = "Visualize solutions from file: " + filename;
ui->messageBox(textFile);
// Variables to hold the values
std::vector<double> theta1_R, theta2_R, theta2_S, theta3_R, theta4_R, theta4_S, theta5_R;
// Column mapping to values
int theta1_R_col = 0;
int theta2_R_col = 1;
int theta2_S_col = 2;
int theta3_R_col = 3;
int theta4_R_col = 4;
int theta4_S_col = 5;
int theta5_R_col = 6;
// Flag to avoid header or not... set to false if file does not have header
bool is_first_row = true;
// CSV parsing
CSVRow row;
while (file >> row)
{
/* Debug code, in case you want see what you are reading from the file
std::string text1 = "Row 1st column: " + row[0];
ui->messageBox(text1);
std::string text2 = "Row 2st column: " + row[1];
ui->messageBox(text2);
std::string text4 = "Row 3st column: " + row[2];
ui->messageBox(text4);
std::string text3 = "Row 4st column: " + row[3];
ui->messageBox(text3);
std::string text5 = "Row 5st column: " + row[4];
ui->messageBox(text5);
std::string text6 = "Row 6st column: " + row[5];
ui->messageBox(text6);
std::string text7 = "Row 7st column: " + row[6];
ui->messageBox(text7);*/
if (is_first_row)
{
std::cout << "Skipping header row, do nothing.." << std::endl;
is_first_row = false;
}
else
{
// This order depends on the header.. the mapping is defined above
double value;
std::stringstream theta1_str(row[theta1_R_col]);
theta1_str >> value;
theta1_R.push_back(value);
std::stringstream theta2_str(row[theta2_R_col]);
theta2_str >> value;
theta2_R.push_back(value);
std::stringstream theta2s_str(row[theta2_S_col]);
theta2s_str >> value;
theta2_S.push_back(value);
std::stringstream theta3_str(row[theta3_R_col]);
theta3_str >> value;
theta3_R.push_back(value);
std::stringstream theta4_str(row[theta4_R_col]);
theta4_str >> value;
theta4_R.push_back(value);
std::stringstream theta4s_str(row[theta4_S_col]);
theta4s_str >> value;
theta4_S.push_back(value);
std::stringstream theta5_str(row[theta5_R_col]);
theta5_str >> value;
theta5_R.push_back(value);
}
}
// Moving the joints
int n_solutions = theta1_R.size();
double deg_to_rad = 3.141592 / 180.0;
for (int i = 0; i < n_solutions; i++)
{
theta1->rotationValue(theta1_R[i]*deg_to_rad);
theta2->rotationValue(theta2_R[i]*deg_to_rad);
theta2->slideValue(theta2_S[i]/10.0);
theta3->rotationValue(theta3_R[i]*deg_to_rad);
theta4->rotationValue(theta4_R[i]*deg_to_rad);
theta4->slideValue(theta4_S[i]/10.0);
theta5->rotationValue(theta5_R[i]*deg_to_rad);
std::string text = "Showing solution " + std::to_string(i + 1) + " / " + std::to_string(n_solutions);
ui->messageBox(text);
}
return true;
}
// Added by F360
#ifdef XI_WIN
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#endif // XI_WIN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment